From 921c4fcee4385e11421e9909890f14c1aef548c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Sun, 10 May 2026 11:27:55 +0200 Subject: [PATCH 01/11] Device posture --- package.json | 36 +- pnpm-lock.yaml | 1055 ++++++++++---------- src-tauri/Cargo.lock | 877 ++++++---------- src-tauri/Cargo.toml | 9 +- src-tauri/posture/Cargo.toml | 15 + src-tauri/posture/src/inspector/linux.rs | 25 + src-tauri/posture/src/inspector/macos.rs | 17 + src-tauri/posture/src/inspector/mod.rs | 6 + src-tauri/posture/src/inspector/windows.rs | 118 +++ src-tauri/posture/src/lib.rs | 129 +++ src-tauri/posture/src/tests/linux.rs | 16 + src-tauri/posture/src/tests/macos.rs | 21 + src-tauri/posture/src/tests/mod.rs | 6 + src-tauri/posture/src/tests/windows.rs | 33 + 14 files changed, 1218 insertions(+), 1145 deletions(-) create mode 100644 src-tauri/posture/Cargo.toml create mode 100644 src-tauri/posture/src/inspector/linux.rs create mode 100644 src-tauri/posture/src/inspector/macos.rs create mode 100644 src-tauri/posture/src/inspector/mod.rs create mode 100644 src-tauri/posture/src/inspector/windows.rs create mode 100644 src-tauri/posture/src/lib.rs create mode 100644 src-tauri/posture/src/tests/linux.rs create mode 100644 src-tauri/posture/src/tests/macos.rs create mode 100644 src-tauri/posture/src/tests/mod.rs create mode 100644 src-tauri/posture/src/tests/windows.rs diff --git a/package.json b/package.json index 08781877..ff2796d7 100644 --- a/package.json +++ b/package.json @@ -56,17 +56,17 @@ "@react-hook/resize-observer": "^2.0.2", "@stablelib/base64": "^2.0.1", "@stablelib/x25519": "^2.0.1", - "@tanstack/query-core": "^5.100.5", + "@tanstack/query-core": "^5.100.9", "@tanstack/react-virtual": "^3.13.24", - "@tauri-apps/api": "^2.10.1", + "@tauri-apps/api": "^2.11.0", "@tauri-apps/plugin-clipboard-manager": "^2.3.2", - "@tauri-apps/plugin-deep-link": "^2.4.8", - "@tauri-apps/plugin-dialog": "^2.7.0", - "@tauri-apps/plugin-fs": "^2.5.0", - "@tauri-apps/plugin-http": "^2.5.8", + "@tauri-apps/plugin-deep-link": "^2.4.9", + "@tauri-apps/plugin-dialog": "^2.7.1", + "@tauri-apps/plugin-fs": "^2.5.1", + "@tauri-apps/plugin-http": "^2.5.9", "@tauri-apps/plugin-log": "^2.8.0", "@tauri-apps/plugin-notification": "^2.3.3", - "@tauri-apps/plugin-opener": "^2.5.3", + "@tauri-apps/plugin-opener": "^2.5.4", "@tauri-apps/plugin-os": "^2.3.2", "@tauri-apps/plugin-process": "^2.3.1", "@tauri-apps/plugin-window-state": "^2.4.1", @@ -92,15 +92,15 @@ "p-timeout": "^6.1.4", "prop-types": "^15.8.1", "radash": "^12.1.1", - "react": "^19.2.5", + "react": "^19.2.6", "react-auth-code-input": "^3.2.1", "react-click-away-listener": "^2.4.1", - "react-dom": "^19.2.5", - "react-hook-form": "^7.74.0", - "react-hotkeys-hook": "^5.2.4", + "react-dom": "^19.2.6", + "react-hook-form": "^7.75.0", + "react-hotkeys-hook": "^5.3.2", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", - "react-qr-code": "^2.0.18", + "react-qr-code": "^2.0.21", "react-router-dom": "^6.30.3", "react-use-websocket": "^4.13.0", "react-virtualized-auto-sizer": "^1.0.26", @@ -109,15 +109,15 @@ "rxjs": "^7.8.2", "use-breakpoint": "^4.0.10", "zod": "^3.25.76", - "zustand": "^5.0.12" + "zustand": "^5.0.13" }, "devDependencies": { - "@biomejs/biome": "^2.4.13", + "@biomejs/biome": "^2.4.14", "@hookform/devtools": "^4.4.0", "@svgr/cli": "^8.1.0", - "@tanstack/react-query": "^5.100.5", - "@tanstack/react-query-devtools": "^5.100.5", - "@tauri-apps/cli": "^2.10.1", + "@tanstack/react-query": "^5.100.9", + "@tanstack/react-query-devtools": "^5.100.9", + "@tauri-apps/cli": "^2.11.1", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", "@types/node": "^24.12.2", @@ -127,7 +127,7 @@ "@vitejs/plugin-react-swc": "^4.3.0", "autoprefixer": "^10.5.0", "npm-run-all": "^4.1.5", - "postcss": "^8.5.12", + "postcss": "^8.5.14", "prettier": "^3.8.3", "sass": "~1.92.1", "typedoc": "^0.28.19", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae5e3e41..83620c22 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,22 +4,19 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - mdast-util-to-hast: 13.2.1 - importers: .: dependencies: '@floating-ui/react': specifier: ^0.27.19 - version: 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 0.27.19(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@hookform/resolvers': specifier: ^3.10.0 - version: 3.10.0(react-hook-form@7.74.0(react@19.2.5)) + version: 3.10.0(react-hook-form@7.75.0(react@19.2.6)) '@react-hook/resize-observer': specifier: ^2.0.2 - version: 2.0.2(react@19.2.5) + version: 2.0.2(react@19.2.6) '@stablelib/base64': specifier: ^2.0.1 version: 2.0.1 @@ -27,29 +24,29 @@ importers: specifier: ^2.0.1 version: 2.0.1 '@tanstack/query-core': - specifier: ^5.100.5 - version: 5.100.5 + specifier: ^5.100.9 + version: 5.100.9 '@tanstack/react-virtual': specifier: ^3.13.24 - version: 3.13.24(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 3.13.24(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@tauri-apps/api': - specifier: ^2.10.1 - version: 2.10.1 + specifier: ^2.11.0 + version: 2.11.0 '@tauri-apps/plugin-clipboard-manager': specifier: ^2.3.2 version: 2.3.2 '@tauri-apps/plugin-deep-link': - specifier: ^2.4.8 - version: 2.4.8 + specifier: ^2.4.9 + version: 2.4.9 '@tauri-apps/plugin-dialog': - specifier: ^2.7.0 - version: 2.7.0 + specifier: ^2.7.1 + version: 2.7.1 '@tauri-apps/plugin-fs': - specifier: ^2.5.0 - version: 2.5.0 + specifier: ^2.5.1 + version: 2.5.1 '@tauri-apps/plugin-http': - specifier: ^2.5.8 - version: 2.5.8 + specifier: ^2.5.9 + version: 2.5.9 '@tauri-apps/plugin-log': specifier: ^2.8.0 version: 2.8.0 @@ -57,8 +54,8 @@ importers: specifier: ^2.3.3 version: 2.3.3 '@tauri-apps/plugin-opener': - specifier: ^2.5.3 - version: 2.5.3 + specifier: ^2.5.4 + version: 2.5.4 '@tauri-apps/plugin-os': specifier: ^2.3.2 version: 2.3.2 @@ -73,7 +70,7 @@ importers: version: 8.1.2 '@use-gesture/react': specifier: ^10.3.1 - version: 10.3.1(react@19.2.5) + version: 10.3.1(react@19.2.6) byte-size: specifier: ^9.0.1 version: 9.0.1 @@ -106,7 +103,7 @@ importers: version: 1.0.3 html-react-parser: specifier: ^5.2.17 - version: 5.2.17(@types/react@19.2.14)(react@19.2.5) + version: 5.2.17(@types/react@19.2.14)(react@19.2.6) itertools: specifier: ^2.6.0 version: 2.6.0 @@ -124,7 +121,7 @@ importers: version: 6.1.0 motion: specifier: ^12.38.0 - version: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) p-timeout: specifier: ^6.1.4 version: 6.1.4 @@ -135,44 +132,44 @@ importers: specifier: ^12.1.1 version: 12.1.1 react: - specifier: ^19.2.5 - version: 19.2.5 + specifier: ^19.2.6 + version: 19.2.6 react-auth-code-input: specifier: ^3.2.1 - version: 3.2.1(react@19.2.5) + version: 3.2.1(react@19.2.6) react-click-away-listener: specifier: ^2.4.1 - version: 2.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 2.4.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react-dom: - specifier: ^19.2.5 - version: 19.2.5(react@19.2.5) + specifier: ^19.2.6 + version: 19.2.6(react@19.2.6) react-hook-form: - specifier: ^7.74.0 - version: 7.74.0(react@19.2.5) + specifier: ^7.75.0 + version: 7.75.0(react@19.2.6) react-hotkeys-hook: - specifier: ^5.2.4 - version: 5.2.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: ^5.3.2 + version: 5.3.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react-loading-skeleton: specifier: ^3.5.0 - version: 3.5.0(react@19.2.5) + version: 3.5.0(react@19.2.6) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.14)(react@19.2.5) + version: 10.1.0(@types/react@19.2.14)(react@19.2.6) react-qr-code: - specifier: ^2.0.18 - version: 2.0.18(react@19.2.5) + specifier: ^2.0.21 + version: 2.0.21(react@19.2.6) react-router-dom: specifier: ^6.30.3 - version: 6.30.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 6.30.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react-use-websocket: specifier: ^4.13.0 version: 4.13.0 react-virtualized-auto-sizer: specifier: ^1.0.26 - version: 1.0.26(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 1.0.26(react-dom@19.2.6(react@19.2.6))(react@19.2.6) recharts: specifier: ^3.8.1 - version: 3.8.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react-is@16.13.1)(react@19.2.5)(redux@5.0.1) + version: 3.8.1(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react-is@16.13.1)(react@19.2.6)(redux@5.0.1) rehype-sanitize: specifier: ^6.0.0 version: 6.0.0 @@ -181,32 +178,32 @@ importers: version: 7.8.2 use-breakpoint: specifier: ^4.0.10 - version: 4.0.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 4.0.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6) zod: specifier: ^3.25.76 version: 3.25.76 zustand: - specifier: ^5.0.12 - version: 5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5)) + specifier: ^5.0.13 + version: 5.0.13(@types/react@19.2.14)(immer@11.1.7)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)) devDependencies: '@biomejs/biome': - specifier: ^2.4.13 - version: 2.4.13 + specifier: ^2.4.14 + version: 2.4.14 '@hookform/devtools': specifier: ^4.4.0 - version: 4.4.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 4.4.0(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.9.3) '@tanstack/react-query': - specifier: ^5.100.5 - version: 5.100.5(react@19.2.5) + specifier: ^5.100.9 + version: 5.100.9(react@19.2.6) '@tanstack/react-query-devtools': - specifier: ^5.100.5 - version: 5.100.5(@tanstack/react-query@5.100.5(react@19.2.5))(react@19.2.5) + specifier: ^5.100.9 + version: 5.100.9(@tanstack/react-query@5.100.9(react@19.2.6))(react@19.2.6) '@tauri-apps/cli': - specifier: ^2.10.1 - version: 2.10.1 + specifier: ^2.11.1 + version: 2.11.1 '@types/file-saver': specifier: ^2.0.7 version: 2.0.7 @@ -224,19 +221,19 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^5.2.0 - version: 5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3)) + version: 5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4)) '@vitejs/plugin-react-swc': specifier: ^4.3.0 - version: 4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3)) + version: 4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4)) autoprefixer: specifier: ^10.5.0 - version: 10.5.0(postcss@8.5.12) + version: 10.5.0(postcss@8.5.14) npm-run-all: specifier: ^4.1.5 version: 4.1.5 postcss: - specifier: ^8.5.12 - version: 8.5.12 + specifier: ^8.5.14 + version: 8.5.14 prettier: specifier: ^3.8.3 version: 3.8.3 @@ -254,7 +251,7 @@ importers: version: 5.9.3 vite: specifier: ^7.3.2 - version: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3) + version: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) packages: @@ -262,8 +259,8 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + '@babel/compat-data@7.29.3': + resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} engines: {node: '>=6.9.0'} '@babel/core@7.29.0': @@ -312,8 +309,8 @@ packages: resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} engines: {node: '>=6.0.0'} hasBin: true @@ -345,59 +342,59 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.4.13': - resolution: {integrity: sha512-gLXOwkOBBg0tr7bDsqlkIh4uFeKuMjxvqsrb1Tukww1iDmHcfr4Uu8MoQxp0Rcte+69+osRNWXwHsu/zxT6XqA==} + '@biomejs/biome@2.4.14': + resolution: {integrity: sha512-TmAvxOEgrpLypzVGJ8FulIZnlyA9TxrO1hyqYrCz9r+bwma9xXxuLA5IuYnj55XQneFx460KjRbx6SWGLkg3bQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.4.13': - resolution: {integrity: sha512-2KImO1jhNFBa2oWConyr0x6flxbQpGKv6902uGXpYM62Xyem8U80j441SyUJ8KyngsmKbQjeIv1q2CQfDkNnYg==} + '@biomejs/cli-darwin-arm64@2.4.14': + resolution: {integrity: sha512-XvgoE9XOawUOQPdmvs4J7wPhi/DLwSCGks3AlPJDmh34O0awRTqCED1HRcRDdpf1Zrp4us4MGOOdIxNpbqNF5Q==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.4.13': - resolution: {integrity: sha512-BKrJklbaFN4p1Ts4kPBczo+PkbsHQg57kmJ+vON9u2t6uN5okYHaSr7h/MutPCWQgg2lglaWoSmm+zhYW+oOkg==} + '@biomejs/cli-darwin-x64@2.4.14': + resolution: {integrity: sha512-jE7hKBCFhOx3uUh+ZkWBfOHxAcILPfhFplNkuID/eZeSTLHzfZzoZxW8fbqY9xXRnPi7jGNAf1iPVR+0yWsM/Q==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.4.13': - resolution: {integrity: sha512-U5MsuBQW25dXaYtqWWSPM3P96H6Y+fHuja3TQpMNnylocHW0tEbtFTDlUj6oM+YJLntvEkQy4grBvQNUD4+RCg==} + '@biomejs/cli-linux-arm64-musl@2.4.14': + resolution: {integrity: sha512-/z+6gqAqqUQTHazwStxSXKHg9b8UvqBmDFRp+c4wYbq2KXhELQDon9EoC9RpmQ8JWkqQx/lIUy/cs+MhzDZp6A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [musl] - '@biomejs/cli-linux-arm64@2.4.13': - resolution: {integrity: sha512-NzkUDSqfvMBrPplKgVr3aXLHZ2NEELvvF4vZxXulEylKWIGqlvNEcwUcj9OLrn75TD3lJ/GIqCVlBwd1MZCuYQ==} + '@biomejs/cli-linux-arm64@2.4.14': + resolution: {integrity: sha512-2TELhZnW5RSLL063l9rc5xLpA0ZIw0Ccwy/0q384rvNAgFw3yI76bd59547yxowdQr5MNPET/xDLrLuvgSeeWQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [glibc] - '@biomejs/cli-linux-x64-musl@2.4.13': - resolution: {integrity: sha512-Z601MienRgTBDza/+u2CH3RSrWoXo9rtr8NK6A4KJzqGgfxx+H3VlyLgTJ4sRo40T3pIsqpTmiOQEvYzQvBRvQ==} + '@biomejs/cli-linux-x64-musl@2.4.14': + resolution: {integrity: sha512-R6BWgJdQOwW9ulJatuTVrQkjnODjqHZkKNOqb1sz++3Noe5LYd0i3PchnOBUCYAPHoPWHhjJqbdZlHEu0hpjdA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [musl] - '@biomejs/cli-linux-x64@2.4.13': - resolution: {integrity: sha512-Az3ZZedYRBo9EQzNnD9SxFcR1G5QsGo6VEc2hIyVPZ1rdKwee/7E9oeBBZFpE8Z44ekxsDQBqbiWGW5ShOhUSQ==} + '@biomejs/cli-linux-x64@2.4.14': + resolution: {integrity: sha512-zHrlQZDBDUz4OLAraYpWKcnLS6HOewBFWYOzY91d1ZjdqZwibOyb6BEu6WuWLugyo0P3riCmsbV9UqV1cSXwQg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [glibc] - '@biomejs/cli-win32-arm64@2.4.13': - resolution: {integrity: sha512-Px9PS2B5/Q183bUwy/5VHqp3J2lzdOCeVGzMpphYfl8oSa7VDCqenBdqWpy6DCy/en4Rbf/Y1RieZF6dJPcc9A==} + '@biomejs/cli-win32-arm64@2.4.14': + resolution: {integrity: sha512-M3EH5hqOI/F/FUA2u4xcLoUgmxd218mvuj/6JL7Hv2toQvr2/AdOvKSpGkoRuWFCtQPVa+ZqkEV3Q5xBA9+XSA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.4.13': - resolution: {integrity: sha512-tTcMkXyBrmHi9BfrD2VNHs/5rYIUKETqsBlYOvSAABwBkJhSDVb5e7wPukftsQbO3WzQkXe6kaztC6WtUOXSoQ==} + '@biomejs/cli-win32-x64@2.4.14': + resolution: {integrity: sha512-WL0EG5qE+EAKomGXbf2g6VnSKJhTL3tXC0QRzWRwA5VpjxNYa6H4P7ZWfymbGE4IhZZQi1KXQ2R0YjwInmz2fA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -787,141 +784,141 @@ packages: '@rolldown/pluginutils@1.0.0-rc.7': resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} - '@rollup/rollup-android-arm-eabi@4.60.2': - resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==} + '@rollup/rollup-android-arm-eabi@4.60.3': + resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.60.2': - resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==} + '@rollup/rollup-android-arm64@4.60.3': + resolution: {integrity: sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.60.2': - resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==} + '@rollup/rollup-darwin-arm64@4.60.3': + resolution: {integrity: sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.60.2': - resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==} + '@rollup/rollup-darwin-x64@4.60.3': + resolution: {integrity: sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.60.2': - resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==} + '@rollup/rollup-freebsd-arm64@4.60.3': + resolution: {integrity: sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.60.2': - resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==} + '@rollup/rollup-freebsd-x64@4.60.3': + resolution: {integrity: sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.60.2': - resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==} + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': + resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.60.2': - resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==} + '@rollup/rollup-linux-arm-musleabihf@4.60.3': + resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.60.2': - resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==} + '@rollup/rollup-linux-arm64-gnu@4.60.3': + resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.60.2': - resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==} + '@rollup/rollup-linux-arm64-musl@4.60.3': + resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.60.2': - resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==} + '@rollup/rollup-linux-loong64-gnu@4.60.3': + resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.60.2': - resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==} + '@rollup/rollup-linux-loong64-musl@4.60.3': + resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.60.2': - resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==} + '@rollup/rollup-linux-ppc64-gnu@4.60.3': + resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.60.2': - resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==} + '@rollup/rollup-linux-ppc64-musl@4.60.3': + resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.60.2': - resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==} + '@rollup/rollup-linux-riscv64-gnu@4.60.3': + resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.60.2': - resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==} + '@rollup/rollup-linux-riscv64-musl@4.60.3': + resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.60.2': - resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==} + '@rollup/rollup-linux-s390x-gnu@4.60.3': + resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.60.2': - resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==} + '@rollup/rollup-linux-x64-gnu@4.60.3': + resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.60.2': - resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==} + '@rollup/rollup-linux-x64-musl@4.60.3': + resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.60.2': - resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==} + '@rollup/rollup-openbsd-x64@4.60.3': + resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.60.2': - resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==} + '@rollup/rollup-openharmony-arm64@4.60.3': + resolution: {integrity: sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.60.2': - resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==} + '@rollup/rollup-win32-arm64-msvc@4.60.3': + resolution: {integrity: sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.60.2': - resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==} + '@rollup/rollup-win32-ia32-msvc@4.60.3': + resolution: {integrity: sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.60.2': - resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==} + '@rollup/rollup-win32-x64-gnu@4.60.3': + resolution: {integrity: sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.60.2': - resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==} + '@rollup/rollup-win32-x64-msvc@4.60.3': + resolution: {integrity: sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==} cpu: [x64] os: [win32] @@ -1055,86 +1052,86 @@ packages: peerDependencies: '@svgr/core': '*' - '@swc/core-darwin-arm64@1.15.30': - resolution: {integrity: sha512-VvpP+vq08HmGYewMWvrdsxh9s2lthz/808zXm8Yu5kaqeR8Yia2b0eYXleHQ3VAjoStUDk6LzTheBW9KXYQdMA==} + '@swc/core-darwin-arm64@1.15.33': + resolution: {integrity: sha512-N+L0uXhuO7FIfzqwgxmzv0zIpV0qEp8wPX3QQs2p4atjMoywup2JTeDlXPw+z9pWJGCae3JjM+tZ6myclI+2gA==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.15.30': - resolution: {integrity: sha512-WiJA0hiZI3nwQAO6mu5RqigtWGDtth4Hiq6rbZxAaQyhIcqKIg5IoMRc1Y071lrNJn29eEDMC86Rq58xgUxlDg==} + '@swc/core-darwin-x64@1.15.33': + resolution: {integrity: sha512-/Il4QHSOhV4FekbsDtkrNmKbsX26oSysvgrRswa/RYOHXAkwXDbB4jaeKq6PsJLSPkzJ2KzQ061gtBnk0vNHfA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.15.30': - resolution: {integrity: sha512-YANuFUo48kIT6plJgCD0keae9HFXfjxsbvsgevqc0hr/07X/p7sAWTFOGYEc2SXcASaK7UvuQqzlbW8pr7R79g==} + '@swc/core-linux-arm-gnueabihf@1.15.33': + resolution: {integrity: sha512-C64hBnBxq4viOPQ8hlx+2lJ23bzZBGnjw7ryALmS+0Q3zHmwO8lw1/DArLENw4Q18/0w5wdEO1k3m1wWNtKGqQ==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.15.30': - resolution: {integrity: sha512-VndG8jaR4ugY6u+iVOT0Q+d2fZd7sLgjPgN8W/Le+3EbZKl+cRfFxV7Eoz4gfLqhmneZPdcIzf9T3LkgkmqNLg==} + '@swc/core-linux-arm64-gnu@1.15.33': + resolution: {integrity: sha512-TRJfnJbX3jqpxRDRoieMzRiCBS5jOmXNb3iQXmcgjFEHKLnAgK1RZRU8Cq1MsPqO4jAJp/ld1G4O3fXuxv85uw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [glibc] - '@swc/core-linux-arm64-musl@1.15.30': - resolution: {integrity: sha512-1SYGs2l0Yyyi0pR/P/NKz/x0kqxkoiw+BXeJjLUdecSk/KasncWlJrc6hOvFSgKHOBrzgM5jwuluKtlT8dnrcA==} + '@swc/core-linux-arm64-musl@1.15.33': + resolution: {integrity: sha512-il7tYM+CpUNzieQbwAjFT1P8zqAhmGWNAGhQZBnxurXZ0aNn+5nqYFTEUKNZl7QibtT0uQXzTZrNGHCIj6Y1Og==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [musl] - '@swc/core-linux-ppc64-gnu@1.15.30': - resolution: {integrity: sha512-TXREtiXeRhbfDFbmhnkIsXpKfzbfT73YkV2ZF6w0sfxgjC5zI2ZAbaCOq25qxvegofj2K93DtOpm9RLaBgqR2g==} + '@swc/core-linux-ppc64-gnu@1.15.33': + resolution: {integrity: sha512-ZtNBwN0Z7CFj9Il0FcPaKdjgP7URyKu/3RfH46vq+0paOBqLj4NYldD6Qo//Duif/7IOtAraUfDOmp0PLAufog==} engines: {node: '>=10'} cpu: [ppc64] os: [linux] libc: [glibc] - '@swc/core-linux-s390x-gnu@1.15.30': - resolution: {integrity: sha512-DCR2YYeyd6DQE4OuDhImouuNcjXEiEdnn1Y0DyGteugPEDvVuvYk8Xddi+4o2SgWH6jiW8/I+3emZvbep1NC+g==} + '@swc/core-linux-s390x-gnu@1.15.33': + resolution: {integrity: sha512-De1IyajoOmhOYYjw/lx66bKlyDpHZTueqwpDrWgf5O7T6d1ODeJJO9/OqMBmrBQc5C+dNnlmIufHsp4QVCWufA==} engines: {node: '>=10'} cpu: [s390x] os: [linux] libc: [glibc] - '@swc/core-linux-x64-gnu@1.15.30': - resolution: {integrity: sha512-5Pizw3NgfOJ5BJOBK8TIRa59xFW2avESTOBDPTAYwZYa1JNDs+KMF9lUfjJiJLM5HiMs/wPheA9eiT0q9m2AoA==} + '@swc/core-linux-x64-gnu@1.15.33': + resolution: {integrity: sha512-mGTH0YxmUN+x6vRN/I6NOk5X0ogNktkwPnJ94IMvR7QjhRDwL0O8RXEDhyUM0YtwWrryBOqaJQBX4zruxEPRGw==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [glibc] - '@swc/core-linux-x64-musl@1.15.30': - resolution: {integrity: sha512-qyqydP/wyH8alcIP4a2hnGSjHLJjm9H7yDFup+CPy9oTahFgLLwnNcv5UHXqO2Qs3AIND+cls5f/Bb6hqpxdgA==} + '@swc/core-linux-x64-musl@1.15.33': + resolution: {integrity: sha512-hj628ZkSEJf6zMf5VMbYrG2O6QqyTIp2qwY6VlCjvIa9lAEZ5c2lfPblCLVGYubTeLJDxadLB/CxqQYOQABeEQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [musl] - '@swc/core-win32-arm64-msvc@1.15.30': - resolution: {integrity: sha512-CaQENgDHVGOg1mSF5sQVgvfFHG9kjMor2rkLMLeLOkfZYNj13ppnJ9+lfaBZLZUMMbnlGQnavCJb8PVBUOso7Q==} + '@swc/core-win32-arm64-msvc@1.15.33': + resolution: {integrity: sha512-GV2oohtN2/5+KSccl86VULu3aT+LrISC8uzgSq0FRnikpD+Zwc+sBlXmoKQ+Db6jI57ITUOIB8jRkdGMABC29g==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.15.30': - resolution: {integrity: sha512-30VdLeGk6fugiUs/kUdJ/pAg7z/zpvVbR11RH60jZ0Z42WIeIniYx0rLEWN7h/pKJ3CopqsQ3RsogCAkRKiA2g==} + '@swc/core-win32-ia32-msvc@1.15.33': + resolution: {integrity: sha512-gtyvzSNR8DHKfFEA2uqb8Ld1myqi6uEg2jyeUq3ikn5ytYs7H8RpZYC8mdy4NXr8hfcdJfCLXPlYaqqfBXpoEQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.15.30': - resolution: {integrity: sha512-4iObHPR+Q4oDY110EF5SF5eIaaVJNpMdG9C0q3Q92BsJ5y467uHz7sYQhP60WYlLFsLQ1el2YrIPUItUAQGOKg==} + '@swc/core-win32-x64-msvc@1.15.33': + resolution: {integrity: sha512-d6fRqQSkJI+kmMEBWaDQ7TMl8+YjLYbwRUPZQ9DY0ORBJeTzOrG0twvfvlZ2xgw6jA0ScQKgfBm4vHLSLl5Hqg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.15.30': - resolution: {integrity: sha512-R8VQbQY1BZcbIF2p3gjlTCwAQzx1A194ugWfwld5y+WgVVWqVKm7eURGGOVbQVubgKWzidP2agomBbg96rZilQ==} + '@swc/core@1.15.33': + resolution: {integrity: sha512-jOlwnFV2xhuuZeAUILGFULeR6vDPfijEJ57evfocwznQldLU3w2cZ9bSDryY9ip+AsM3r1NJKzf47V2NXebkeQ==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -1148,20 +1145,20 @@ packages: '@swc/types@0.1.26': resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} - '@tanstack/query-core@5.100.5': - resolution: {integrity: sha512-t20KrhKkf0HXzqQkPbJ5erhFesup68BAbwFgYmTrS7bxMF7O5MdmL8jUkik4thsG7Hg00fblz30h6yF1d5TxGg==} + '@tanstack/query-core@5.100.9': + resolution: {integrity: sha512-SJSFw1S8+kQ0+knv/XGfrbocWoAlT7vDKsSImtLx3ZPQmEcR46hkDjLSvynSy25N8Ms4tIEini1FuBd5k7IscQ==} - '@tanstack/query-devtools@5.100.5': - resolution: {integrity: sha512-SuCkVCqqliRYJvm+LEL2U/TcFv92zTnHj6OGrJFHp1v/RsiwamI+ZDgQzbeUrLsJb8/Nj/52aIw0NyDMcVHl4A==} + '@tanstack/query-devtools@5.100.9': + resolution: {integrity: sha512-gqiptrTIhbK2PuCaPRHmWXfJG1NGYVFpAr0HqogEqiSBNB5xDz6fmesQt7w4WgMOqOQPnPHJ3ZDMuhDaXvNO8g==} - '@tanstack/react-query-devtools@5.100.5': - resolution: {integrity: sha512-bItQERx7dJoiI0WEoS4tIrvNnmk4kUYsaQLdIpm4o9Kttmsi5B6xlY6JBDkavstR3hH/R2+VT5dr3L5LBFPW4g==} + '@tanstack/react-query-devtools@5.100.9': + resolution: {integrity: sha512-mM3slaVGXJmz+pOLgXdANj75ikgQCyudyl3kmFvm6brI1JyVeY/+IeD17uDHIvZrD8hfoO2sdZ54RFsHdYAuhA==} peerDependencies: - '@tanstack/react-query': ^5.100.5 + '@tanstack/react-query': ^5.100.9 react: ^18 || ^19 - '@tanstack/react-query@5.100.5': - resolution: {integrity: sha512-aNwj1mi2v2bQ9IxkyR1grLOUkv3BYWoykHy9KDyLNbjC3tsahbOHJibK+Wjtr1wRhG59/AvJhiJG5OlthaCgJA==} + '@tanstack/react-query@5.100.9': + resolution: {integrity: sha512-Oa44XkaI3kCNN6ME0KByU3xT3SEUNOMfZpHxL6+wFoTm+OeUFYHKdeYVe0aOXlRDm/f15sgLwEt2HDorIdW8+A==} peerDependencies: react: ^18 || ^19 @@ -1174,99 +1171,99 @@ packages: '@tanstack/virtual-core@3.14.0': resolution: {integrity: sha512-JLANqGy/D6k4Ujmh8Tr25lGimuOXNiaVyXaCAZS0W+1390sADdGnyUdSWNIfd49gebtIxGMij4IktRVzrdr12Q==} - '@tauri-apps/api@2.10.1': - resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==} + '@tauri-apps/api@2.11.0': + resolution: {integrity: sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==} - '@tauri-apps/cli-darwin-arm64@2.10.1': - resolution: {integrity: sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==} + '@tauri-apps/cli-darwin-arm64@2.11.1': + resolution: {integrity: sha512-6eEKMBXsQPCuM1EmvrjT2+aBuxWQuFdKdW8pzNuNQtpq45nEEpBlD5gr8pUeAyOU1DQKlkFaEc/MPBxb/Pfjtg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.10.1': - resolution: {integrity: sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==} + '@tauri-apps/cli-darwin-x64@2.11.1': + resolution: {integrity: sha512-LQUO7exfRWjWALNhetph5guWpMeHphRpokOLk0OIbTTExaNwJNFu3I4vb+CCM/4G/QGoZe/5XikZOJdNEFP1ig==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tauri-apps/cli-linux-arm-gnueabihf@2.10.1': - resolution: {integrity: sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.1': + resolution: {integrity: sha512-5i/awiBCRRhOUG8yjn0fMHXIWD5Ez8eEk5LtvOxyQrKuJkRaZDvnbIjZbE183blAwkoA4xN3aO/prJiqscl02Q==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.10.1': - resolution: {integrity: sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==} + '@tauri-apps/cli-linux-arm64-gnu@2.11.1': + resolution: {integrity: sha512-9LrwDw3S9Fygtw/Q6WDhOP+3svJRGAsejeE+GKrc0eO1ThMVhwi2LL6hw4dlKw93IfS7VY1G19sWGxJ/NcU4nA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-arm64-musl@2.10.1': - resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} + '@tauri-apps/cli-linux-arm64-musl@2.11.1': + resolution: {integrity: sha512-mNA5dbbqPqDUdTIwdUYYuhO2GvIe9UnB2r0VU2njxBOS3Opbx4gKNC5yP0Iu4rYmEmqdlwry9VzGZQ3wq9dyFg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': - resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} + '@tauri-apps/cli-linux-riscv64-gnu@2.11.1': + resolution: {integrity: sha512-fZj3Gwq+6fUs305T5WQiD5iSGJw+j/4w/HGmk4sHDAcy+rp9zU5eaxB7nOyz5/I/nkNAuKPqfp6uIbiUBXkBCw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-x64-gnu@2.10.1': - resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} + '@tauri-apps/cli-linux-x64-gnu@2.11.1': + resolution: {integrity: sha512-XFxGxOvHM7jjeD6ozCKdGfhzJ7lERYDGZl1/Kb4fsvchaJsfLJ981TlyTG8Qy/gFq+f5GitH3bfrX9JAkjPEyw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-x64-musl@2.10.1': - resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} + '@tauri-apps/cli-linux-x64-musl@2.11.1': + resolution: {integrity: sha512-d5C2/Zm+68v7R9wTuTCjRQEVrWjcdMkJBZ1+rXse+QdMMlTB9+u9PDNDLw9PQflWxYLaYZ7tjxxL9Nb9II6PbA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@tauri-apps/cli-win32-arm64-msvc@2.10.1': - resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} + '@tauri-apps/cli-win32-arm64-msvc@2.11.1': + resolution: {integrity: sha512-YdeVWFAR1pTXzUU6NLstPq4G6OLxuDrXCXEBdmBH+5EZIDXUx0D2kJlz3+YjpazkKvAzYpgziTsyRagls0OfRQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.10.1': - resolution: {integrity: sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==} + '@tauri-apps/cli-win32-ia32-msvc@2.11.1': + resolution: {integrity: sha512-VBGkuH0eB9K9LLSMv361Gzr5Ou72sCS4+ztpmkWEQ+wd/amhcYOsf3X6qn1RJZDzIhiOYHJEOysZUC3baD01rA==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.10.1': - resolution: {integrity: sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==} + '@tauri-apps/cli-win32-x64-msvc@2.11.1': + resolution: {integrity: sha512-b3ORhIAKgp9ZYY+zBt7b7r0kLU2kjvyGF0+MS2SBym3emsweGPybEqocJcmtMuxyBhkOKHP4CiuEJEDuAlTx6A==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tauri-apps/cli@2.10.1': - resolution: {integrity: sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==} + '@tauri-apps/cli@2.11.1': + resolution: {integrity: sha512-rpEbaJ/HzNb6fwsquwoAbq29/Vt4gADhS423A8fdkwL4edJ0wZmoB8ar7O6JPDL834MUKOCm/rrJ7c9oAaEaYQ==} engines: {node: '>= 10'} hasBin: true '@tauri-apps/plugin-clipboard-manager@2.3.2': resolution: {integrity: sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ==} - '@tauri-apps/plugin-deep-link@2.4.8': - resolution: {integrity: sha512-Cd2Cs960MGuGONeIwxOPx9wqwedetAHOGlwK5boJ/SMTfAtAyfErpfVPEn+EJzgXsJun8EKzsEumHjr+64V4fw==} + '@tauri-apps/plugin-deep-link@2.4.9': + resolution: {integrity: sha512-u0SKOUHnJ1wqeqXsDFq2+kASCBj9xxbG0g9XZWPy9SOmU4wXtp6b/wiYpm6oH6/5fBTQsLqnLhIvqLBRpgHJlA==} - '@tauri-apps/plugin-dialog@2.7.0': - resolution: {integrity: sha512-4nS/hfGMGCXiAS3LtVjH9AgsSAPJeG/7R+q8agTFqytjnMa4Zq95Bq8WzVDkckpanX+yyRHXnRtrKXkANKDHvw==} + '@tauri-apps/plugin-dialog@2.7.1': + resolution: {integrity: sha512-OK1UBXYt+ojcmxMktzzuyonYIFta8CmAASpX+CA+DTGK24KlHjhYI6x2iOJ/TjZF4N7/ACK1oFmEOjIY9IhzOQ==} - '@tauri-apps/plugin-fs@2.5.0': - resolution: {integrity: sha512-c83kbz61AK+rKjhS+je9+stIO27nXj7p9cqeg36TwkIUtxpCFTttlHHtqon6h6FN54cXjyAjlMPOJcW3mwE5XQ==} + '@tauri-apps/plugin-fs@2.5.1': + resolution: {integrity: sha512-9Lz+Jopp6QyeEWhlpkMx4R/+P9HgR+AVAI4vOZhlT8Xaymtz8iVI/Ov984/XTqgJz/5gz5NretqPB/XEMS3NhQ==} - '@tauri-apps/plugin-http@2.5.8': - resolution: {integrity: sha512-oxd7oypzQeu8kAfFCrw534Kq7Cw+NzozcnCY21O4rz3A+veJiIiuSCMIprgGcZOcLAXFP9GmDhKUbhuKWcunRw==} + '@tauri-apps/plugin-http@2.5.9': + resolution: {integrity: sha512-lCiY0+vs4HvIUSvZrBs8TC3TiCB0MOPRmiUjTq4prW7SlcJE2jdLeT6KBsJrT9Tlplufl7W1pY6SFAO3gCWxDA==} '@tauri-apps/plugin-log@2.8.0': resolution: {integrity: sha512-a+7rOq3MJwpTOLLKbL8d0qGZ85hgHw5pNOWusA9o3cf7cEgtYHiGY/+O8fj8MvywQIGqFv0da2bYQDlrqLE7rw==} @@ -1274,8 +1271,8 @@ packages: '@tauri-apps/plugin-notification@2.3.3': resolution: {integrity: sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==} - '@tauri-apps/plugin-opener@2.5.3': - resolution: {integrity: sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==} + '@tauri-apps/plugin-opener@2.5.4': + resolution: {integrity: sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==} '@tauri-apps/plugin-os@2.3.2': resolution: {integrity: sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A==} @@ -1337,6 +1334,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/file-saver@2.0.7': resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} @@ -1378,8 +1378,8 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@ungap/structured-clone@1.3.1': + resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} '@use-gesture/core@10.3.1': resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==} @@ -1453,8 +1453,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.23: - resolution: {integrity: sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==} + baseline-browser-mapping@2.10.27: + resolution: {integrity: sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==} engines: {node: '>=6.0.0'} hasBin: true @@ -1505,8 +1505,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001791: - resolution: {integrity: sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==} + caniuse-lite@1.0.30001792: + resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1749,8 +1749,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.344: - resolution: {integrity: sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==} + electron-to-chromium@1.5.352: + resolution: {integrity: sha512-9wHk8x6dyuimoe18EdiDPWKExNdxYqo4fn4FwOVVper6RxT3cmpBwBkWWfSOCYJjQdIco/nPhJhNLmn4Ufg1Yg==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1790,8 +1790,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - es-toolkit@1.46.0: - resolution: {integrity: sha512-IToJ6ct9OLl5zz6WsC/1vZEwfSZ7Myil+ygl5Tf30Xjn9AEkzNB4kqp2G7VUJKF1DtTx/ra5M5KLlXvzOg51BA==} + es-toolkit@1.46.1: + resolution: {integrity: sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==} esbuild@0.27.7: resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} @@ -1986,8 +1986,8 @@ packages: immer@10.2.0: resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} - immer@11.1.4: - resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} + immer@11.1.7: + resolution: {integrity: sha512-LFVFtAROHcDy1er5UI6nodRFnZ2SgdCXhfNSI+DpObO8N7Pur/muBGsjzH5wpnFHCYhYVQxZskCkV4koQ//3/Q==} immutable@5.1.5: resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==} @@ -2043,8 +2043,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} is-data-view@1.0.2: @@ -2359,8 +2359,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2467,8 +2467,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.12: - resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} prettier@2.8.8: @@ -2511,19 +2511,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-dom@19.2.5: - resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} + react-dom@19.2.6: + resolution: {integrity: sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==} peerDependencies: - react: ^19.2.5 + react: ^19.2.6 - react-hook-form@7.74.0: - resolution: {integrity: sha512-yR6wHr99p9wFv686jhRWVSFhUvDvNbdUf2dKlbno8/VKOCuoNobDGC6S+M2dua9A9Yo8vpcrp8assIYbsZCQ9g==} + react-hook-form@7.75.0: + resolution: {integrity: sha512-Ovv94H+0p3sJ7B9B5QxPuCP1u8V/cHuVGyH55cSwodYDtoJwK+fqk3vjfIgSX59I2U/bU4z0nRJ9HMLpNiWEmw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-hotkeys-hook@5.2.4: - resolution: {integrity: sha512-BgKg+A1+TawkYluh5Bo4cTmcgMN5L29uhJbDUQdHwPX+qgXRjIPYU5kIDHyxnAwCkCBiu9V5OpB2mpyeluVF2A==} + react-hotkeys-hook@5.3.2: + resolution: {integrity: sha512-DDDy9xK6mbTQ6aPlQvIl0dA/a90T/AWml4Rm21JXFDLlRHalIg4/Rv3equUQYs5xPTWq+oEl6RD7mi/nBpU3Uw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' @@ -2545,8 +2545,8 @@ packages: react-property@2.0.2: resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==} - react-qr-code@2.0.18: - resolution: {integrity: sha512-v1Jqz7urLMhkO6jkgJuBYhnqvXagzceg3qJUWayuCK/c6LTIonpWbwxR1f1APGd4xrW/QcQEovNrAojbUz65Tg==} + react-qr-code@2.0.21: + resolution: {integrity: sha512-xaywjo0eaF4S3LOz6ns5eoPbM2E+q9HYl4VATYpxK4bBniOhQ9noY2RJ9G4SnZFhUwzx63FUT6KdHzfKgUwyuQ==} peerDependencies: react: '*' @@ -2593,8 +2593,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.2.5: - resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} + react@19.2.6: + resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==} engines: {node: '>=0.10.0'} read-pkg@3.0.0: @@ -2654,8 +2654,8 @@ packages: engines: {node: '>= 0.4'} hasBin: true - rollup@4.60.2: - resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==} + rollup@4.60.3: + resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2931,6 +2931,7 @@ packages: uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true validate-npm-package-license@3.0.4: @@ -3023,8 +3024,8 @@ packages: resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} engines: {node: '>= 6'} - yaml@2.8.3: - resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + yaml@2.8.4: + resolution: {integrity: sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==} engines: {node: '>= 14.6'} hasBin: true @@ -3039,8 +3040,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zustand@5.0.12: - resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} + zustand@5.0.13: + resolution: {integrity: sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -3068,7 +3069,7 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.0': {} + '@babel/compat-data@7.29.3': {} '@babel/core@7.29.0': dependencies: @@ -3077,7 +3078,7 @@ snapshots: '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 @@ -3092,7 +3093,7 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -3100,7 +3101,7 @@ snapshots: '@babel/helper-compilation-targets@7.28.6': dependencies: - '@babel/compat-data': 7.29.0 + '@babel/compat-data': 7.29.3 '@babel/helper-validator-option': 7.27.1 browserslist: 4.28.2 lru-cache: 5.1.1 @@ -3137,7 +3138,7 @@ snapshots: '@babel/template': 7.28.6 '@babel/types': 7.29.0 - '@babel/parser@7.29.2': + '@babel/parser@7.29.3': dependencies: '@babel/types': 7.29.0 @@ -3156,7 +3157,7 @@ snapshots: '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@babel/traverse@7.29.0': @@ -3164,7 +3165,7 @@ snapshots: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/template': 7.28.6 '@babel/types': 7.29.0 debug: 4.4.3 @@ -3176,39 +3177,39 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.4.13': + '@biomejs/biome@2.4.14': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.4.13 - '@biomejs/cli-darwin-x64': 2.4.13 - '@biomejs/cli-linux-arm64': 2.4.13 - '@biomejs/cli-linux-arm64-musl': 2.4.13 - '@biomejs/cli-linux-x64': 2.4.13 - '@biomejs/cli-linux-x64-musl': 2.4.13 - '@biomejs/cli-win32-arm64': 2.4.13 - '@biomejs/cli-win32-x64': 2.4.13 - - '@biomejs/cli-darwin-arm64@2.4.13': + '@biomejs/cli-darwin-arm64': 2.4.14 + '@biomejs/cli-darwin-x64': 2.4.14 + '@biomejs/cli-linux-arm64': 2.4.14 + '@biomejs/cli-linux-arm64-musl': 2.4.14 + '@biomejs/cli-linux-x64': 2.4.14 + '@biomejs/cli-linux-x64-musl': 2.4.14 + '@biomejs/cli-win32-arm64': 2.4.14 + '@biomejs/cli-win32-x64': 2.4.14 + + '@biomejs/cli-darwin-arm64@2.4.14': optional: true - '@biomejs/cli-darwin-x64@2.4.13': + '@biomejs/cli-darwin-x64@2.4.14': optional: true - '@biomejs/cli-linux-arm64-musl@2.4.13': + '@biomejs/cli-linux-arm64-musl@2.4.14': optional: true - '@biomejs/cli-linux-arm64@2.4.13': + '@biomejs/cli-linux-arm64@2.4.14': optional: true - '@biomejs/cli-linux-x64-musl@2.4.13': + '@biomejs/cli-linux-x64-musl@2.4.14': optional: true - '@biomejs/cli-linux-x64@2.4.13': + '@biomejs/cli-linux-x64@2.4.14': optional: true - '@biomejs/cli-win32-arm64@2.4.13': + '@biomejs/cli-win32-arm64@2.4.14': optional: true - '@biomejs/cli-win32-x64@2.4.13': + '@biomejs/cli-win32-x64@2.4.14': optional: true '@emotion/babel-plugin@11.13.5': @@ -3243,17 +3244,17 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5)': + '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.2 '@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.2.5) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.6) '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 19.2.5 + react: 19.2.6 optionalDependencies: '@types/react': 19.2.14 transitivePeerDependencies: @@ -3269,16 +3270,16 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.2 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5) + '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6) '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.5) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.6) '@emotion/utils': 1.4.2 - react: 19.2.5 + react: 19.2.6 optionalDependencies: '@types/react': 19.2.14 transitivePeerDependencies: @@ -3286,9 +3287,9 @@ snapshots: '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.5)': + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.6)': dependencies: - react: 19.2.5 + react: 19.2.6 '@emotion/utils@1.4.2': {} @@ -3381,18 +3382,18 @@ snapshots: '@floating-ui/core': 1.7.5 '@floating-ui/utils': 0.2.11 - '@floating-ui/react-dom@2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@floating-ui/react-dom@2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@floating-ui/dom': 1.7.6 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) - '@floating-ui/react@0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@floating-ui/react@0.27.19(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@floating-ui/utils': 0.2.11 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) tabbable: 6.4.0 '@floating-ui/utils@0.2.11': {} @@ -3405,25 +3406,25 @@ snapshots: '@shikijs/types': 3.23.0 '@shikijs/vscode-textmate': 10.0.2 - '@hookform/devtools@4.4.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@hookform/devtools@4.4.0(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: - '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5) + '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6) '@types/lodash': 4.17.24 - little-state-machine: 4.8.1(react@19.2.5) + little-state-machine: 4.8.1(react@19.2.6) lodash: 4.18.1 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) - react-simple-animate: 3.5.3(react-dom@19.2.5(react@19.2.5)) - use-deep-compare-effect: 1.8.1(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + react-simple-animate: 3.5.3(react-dom@19.2.6(react@19.2.6)) + use-deep-compare-effect: 1.8.1(react@19.2.6) uuid: 8.3.2 transitivePeerDependencies: - '@types/react' - supports-color - '@hookform/resolvers@3.10.0(react-hook-form@7.74.0(react@19.2.5))': + '@hookform/resolvers@3.10.0(react-hook-form@7.75.0(react@19.2.6))': dependencies: - react-hook-form: 7.74.0(react@19.2.5) + react-hook-form: 7.75.0(react@19.2.6) '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -3505,31 +3506,31 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.6 optional: true - '@react-hook/latest@1.0.3(react@19.2.5)': + '@react-hook/latest@1.0.3(react@19.2.6)': dependencies: - react: 19.2.5 + react: 19.2.6 - '@react-hook/passive-layout-effect@1.2.1(react@19.2.5)': + '@react-hook/passive-layout-effect@1.2.1(react@19.2.6)': dependencies: - react: 19.2.5 + react: 19.2.6 - '@react-hook/resize-observer@2.0.2(react@19.2.5)': + '@react-hook/resize-observer@2.0.2(react@19.2.6)': dependencies: - '@react-hook/latest': 1.0.3(react@19.2.5) - '@react-hook/passive-layout-effect': 1.2.1(react@19.2.5) - react: 19.2.5 + '@react-hook/latest': 1.0.3(react@19.2.6) + '@react-hook/passive-layout-effect': 1.2.1(react@19.2.6) + react: 19.2.6 - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1))(react@19.2.5)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1))(react@19.2.6)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 - immer: 11.1.4 + immer: 11.1.7 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) reselect: 5.1.1 optionalDependencies: - react: 19.2.5 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1) + react: 19.2.6 + react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1) '@remix-run/router@1.23.2': {} @@ -3537,79 +3538,79 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.7': {} - '@rollup/rollup-android-arm-eabi@4.60.2': + '@rollup/rollup-android-arm-eabi@4.60.3': optional: true - '@rollup/rollup-android-arm64@4.60.2': + '@rollup/rollup-android-arm64@4.60.3': optional: true - '@rollup/rollup-darwin-arm64@4.60.2': + '@rollup/rollup-darwin-arm64@4.60.3': optional: true - '@rollup/rollup-darwin-x64@4.60.2': + '@rollup/rollup-darwin-x64@4.60.3': optional: true - '@rollup/rollup-freebsd-arm64@4.60.2': + '@rollup/rollup-freebsd-arm64@4.60.3': optional: true - '@rollup/rollup-freebsd-x64@4.60.2': + '@rollup/rollup-freebsd-x64@4.60.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.60.2': + '@rollup/rollup-linux-arm-musleabihf@4.60.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.60.2': + '@rollup/rollup-linux-arm64-gnu@4.60.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.60.2': + '@rollup/rollup-linux-arm64-musl@4.60.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.60.2': + '@rollup/rollup-linux-loong64-gnu@4.60.3': optional: true - '@rollup/rollup-linux-loong64-musl@4.60.2': + '@rollup/rollup-linux-loong64-musl@4.60.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.60.2': + '@rollup/rollup-linux-ppc64-gnu@4.60.3': optional: true - '@rollup/rollup-linux-ppc64-musl@4.60.2': + '@rollup/rollup-linux-ppc64-musl@4.60.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.60.2': + '@rollup/rollup-linux-riscv64-gnu@4.60.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.60.2': + '@rollup/rollup-linux-riscv64-musl@4.60.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.60.2': + '@rollup/rollup-linux-s390x-gnu@4.60.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.60.2': + '@rollup/rollup-linux-x64-gnu@4.60.3': optional: true - '@rollup/rollup-linux-x64-musl@4.60.2': + '@rollup/rollup-linux-x64-musl@4.60.3': optional: true - '@rollup/rollup-openbsd-x64@4.60.2': + '@rollup/rollup-openbsd-x64@4.60.3': optional: true - '@rollup/rollup-openharmony-arm64@4.60.2': + '@rollup/rollup-openharmony-arm64@4.60.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.60.2': + '@rollup/rollup-win32-arm64-msvc@4.60.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.60.2': + '@rollup/rollup-win32-ia32-msvc@4.60.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.60.2': + '@rollup/rollup-win32-x64-gnu@4.60.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.60.2': + '@rollup/rollup-win32-x64-msvc@4.60.3': optional: true '@shikijs/engine-oniguruma@3.23.0': @@ -3764,59 +3765,59 @@ snapshots: transitivePeerDependencies: - typescript - '@swc/core-darwin-arm64@1.15.30': + '@swc/core-darwin-arm64@1.15.33': optional: true - '@swc/core-darwin-x64@1.15.30': + '@swc/core-darwin-x64@1.15.33': optional: true - '@swc/core-linux-arm-gnueabihf@1.15.30': + '@swc/core-linux-arm-gnueabihf@1.15.33': optional: true - '@swc/core-linux-arm64-gnu@1.15.30': + '@swc/core-linux-arm64-gnu@1.15.33': optional: true - '@swc/core-linux-arm64-musl@1.15.30': + '@swc/core-linux-arm64-musl@1.15.33': optional: true - '@swc/core-linux-ppc64-gnu@1.15.30': + '@swc/core-linux-ppc64-gnu@1.15.33': optional: true - '@swc/core-linux-s390x-gnu@1.15.30': + '@swc/core-linux-s390x-gnu@1.15.33': optional: true - '@swc/core-linux-x64-gnu@1.15.30': + '@swc/core-linux-x64-gnu@1.15.33': optional: true - '@swc/core-linux-x64-musl@1.15.30': + '@swc/core-linux-x64-musl@1.15.33': optional: true - '@swc/core-win32-arm64-msvc@1.15.30': + '@swc/core-win32-arm64-msvc@1.15.33': optional: true - '@swc/core-win32-ia32-msvc@1.15.30': + '@swc/core-win32-ia32-msvc@1.15.33': optional: true - '@swc/core-win32-x64-msvc@1.15.30': + '@swc/core-win32-x64-msvc@1.15.33': optional: true - '@swc/core@1.15.30': + '@swc/core@1.15.33': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.26 optionalDependencies: - '@swc/core-darwin-arm64': 1.15.30 - '@swc/core-darwin-x64': 1.15.30 - '@swc/core-linux-arm-gnueabihf': 1.15.30 - '@swc/core-linux-arm64-gnu': 1.15.30 - '@swc/core-linux-arm64-musl': 1.15.30 - '@swc/core-linux-ppc64-gnu': 1.15.30 - '@swc/core-linux-s390x-gnu': 1.15.30 - '@swc/core-linux-x64-gnu': 1.15.30 - '@swc/core-linux-x64-musl': 1.15.30 - '@swc/core-win32-arm64-msvc': 1.15.30 - '@swc/core-win32-ia32-msvc': 1.15.30 - '@swc/core-win32-x64-msvc': 1.15.30 + '@swc/core-darwin-arm64': 1.15.33 + '@swc/core-darwin-x64': 1.15.33 + '@swc/core-linux-arm-gnueabihf': 1.15.33 + '@swc/core-linux-arm64-gnu': 1.15.33 + '@swc/core-linux-arm64-musl': 1.15.33 + '@swc/core-linux-ppc64-gnu': 1.15.33 + '@swc/core-linux-s390x-gnu': 1.15.33 + '@swc/core-linux-x64-gnu': 1.15.33 + '@swc/core-linux-x64-musl': 1.15.33 + '@swc/core-win32-arm64-msvc': 1.15.33 + '@swc/core-win32-ia32-msvc': 1.15.33 + '@swc/core-win32-x64-msvc': 1.15.33 '@swc/counter@0.1.3': {} @@ -3824,125 +3825,125 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@tanstack/query-core@5.100.5': {} + '@tanstack/query-core@5.100.9': {} - '@tanstack/query-devtools@5.100.5': {} + '@tanstack/query-devtools@5.100.9': {} - '@tanstack/react-query-devtools@5.100.5(@tanstack/react-query@5.100.5(react@19.2.5))(react@19.2.5)': + '@tanstack/react-query-devtools@5.100.9(@tanstack/react-query@5.100.9(react@19.2.6))(react@19.2.6)': dependencies: - '@tanstack/query-devtools': 5.100.5 - '@tanstack/react-query': 5.100.5(react@19.2.5) - react: 19.2.5 + '@tanstack/query-devtools': 5.100.9 + '@tanstack/react-query': 5.100.9(react@19.2.6) + react: 19.2.6 - '@tanstack/react-query@5.100.5(react@19.2.5)': + '@tanstack/react-query@5.100.9(react@19.2.6)': dependencies: - '@tanstack/query-core': 5.100.5 - react: 19.2.5 + '@tanstack/query-core': 5.100.9 + react: 19.2.6 - '@tanstack/react-virtual@3.13.24(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@tanstack/react-virtual@3.13.24(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@tanstack/virtual-core': 3.14.0 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) '@tanstack/virtual-core@3.14.0': {} - '@tauri-apps/api@2.10.1': {} + '@tauri-apps/api@2.11.0': {} - '@tauri-apps/cli-darwin-arm64@2.10.1': + '@tauri-apps/cli-darwin-arm64@2.11.1': optional: true - '@tauri-apps/cli-darwin-x64@2.10.1': + '@tauri-apps/cli-darwin-x64@2.11.1': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.10.1': + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.1': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.10.1': + '@tauri-apps/cli-linux-arm64-gnu@2.11.1': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.10.1': + '@tauri-apps/cli-linux-arm64-musl@2.11.1': optional: true - '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': + '@tauri-apps/cli-linux-riscv64-gnu@2.11.1': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.10.1': + '@tauri-apps/cli-linux-x64-gnu@2.11.1': optional: true - '@tauri-apps/cli-linux-x64-musl@2.10.1': + '@tauri-apps/cli-linux-x64-musl@2.11.1': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.10.1': + '@tauri-apps/cli-win32-arm64-msvc@2.11.1': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.10.1': + '@tauri-apps/cli-win32-ia32-msvc@2.11.1': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.10.1': + '@tauri-apps/cli-win32-x64-msvc@2.11.1': optional: true - '@tauri-apps/cli@2.10.1': + '@tauri-apps/cli@2.11.1': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.10.1 - '@tauri-apps/cli-darwin-x64': 2.10.1 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.10.1 - '@tauri-apps/cli-linux-arm64-gnu': 2.10.1 - '@tauri-apps/cli-linux-arm64-musl': 2.10.1 - '@tauri-apps/cli-linux-riscv64-gnu': 2.10.1 - '@tauri-apps/cli-linux-x64-gnu': 2.10.1 - '@tauri-apps/cli-linux-x64-musl': 2.10.1 - '@tauri-apps/cli-win32-arm64-msvc': 2.10.1 - '@tauri-apps/cli-win32-ia32-msvc': 2.10.1 - '@tauri-apps/cli-win32-x64-msvc': 2.10.1 + '@tauri-apps/cli-darwin-arm64': 2.11.1 + '@tauri-apps/cli-darwin-x64': 2.11.1 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.11.1 + '@tauri-apps/cli-linux-arm64-gnu': 2.11.1 + '@tauri-apps/cli-linux-arm64-musl': 2.11.1 + '@tauri-apps/cli-linux-riscv64-gnu': 2.11.1 + '@tauri-apps/cli-linux-x64-gnu': 2.11.1 + '@tauri-apps/cli-linux-x64-musl': 2.11.1 + '@tauri-apps/cli-win32-arm64-msvc': 2.11.1 + '@tauri-apps/cli-win32-ia32-msvc': 2.11.1 + '@tauri-apps/cli-win32-x64-msvc': 2.11.1 '@tauri-apps/plugin-clipboard-manager@2.3.2': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 - '@tauri-apps/plugin-deep-link@2.4.8': + '@tauri-apps/plugin-deep-link@2.4.9': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 - '@tauri-apps/plugin-dialog@2.7.0': + '@tauri-apps/plugin-dialog@2.7.1': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 - '@tauri-apps/plugin-fs@2.5.0': + '@tauri-apps/plugin-fs@2.5.1': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 - '@tauri-apps/plugin-http@2.5.8': + '@tauri-apps/plugin-http@2.5.9': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@tauri-apps/plugin-log@2.8.0': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@tauri-apps/plugin-notification@2.3.3': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 - '@tauri-apps/plugin-opener@2.5.3': + '@tauri-apps/plugin-opener@2.5.4': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@tauri-apps/plugin-os@2.3.2': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@tauri-apps/plugin-process@2.3.1': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@tauri-apps/plugin-window-state@2.4.1': dependencies: - '@tauri-apps/api': 2.10.1 + '@tauri-apps/api': 2.11.0 '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 @@ -3954,7 +3955,7 @@ snapshots: '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': @@ -3993,10 +3994,12 @@ snapshots: '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} + '@types/file-saver@2.0.7': {} '@types/hast@3.0.4': @@ -4035,24 +4038,24 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@ungap/structured-clone@1.3.0': {} + '@ungap/structured-clone@1.3.1': {} '@use-gesture/core@10.3.1': {} - '@use-gesture/react@10.3.1(react@19.2.5)': + '@use-gesture/react@10.3.1(react@19.2.6)': dependencies: '@use-gesture/core': 10.3.1 - react: 19.2.5 + react: 19.2.6 - '@vitejs/plugin-react-swc@4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3))': + '@vitejs/plugin-react-swc@4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - '@swc/core': 1.15.30 - vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3) + '@swc/core': 1.15.33 + vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3))': + '@vitejs/plugin-react@5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -4060,7 +4063,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3) + vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) transitivePeerDependencies: - supports-color @@ -4093,13 +4096,13 @@ snapshots: async-function@1.0.0: {} - autoprefixer@10.5.0(postcss@8.5.12): + autoprefixer@10.5.0(postcss@8.5.14): dependencies: browserslist: 4.28.2 - caniuse-lite: 1.0.30001791 + caniuse-lite: 1.0.30001792 fraction.js: 5.3.4 picocolors: 1.1.1 - postcss: 8.5.12 + postcss: 8.5.14 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -4118,7 +4121,7 @@ snapshots: balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.23: {} + baseline-browser-mapping@2.10.27: {} boolbase@1.0.0: {} @@ -4137,9 +4140,9 @@ snapshots: browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.23 - caniuse-lite: 1.0.30001791 - electron-to-chromium: 1.5.344 + baseline-browser-mapping: 2.10.27 + caniuse-lite: 1.0.30001792 + electron-to-chromium: 1.5.352 node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) @@ -4166,7 +4169,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001791: {} + caniuse-lite@1.0.30001792: {} ccount@2.0.1: {} @@ -4406,7 +4409,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.344: {} + electron-to-chromium@1.5.352: {} emoji-regex@8.0.0: {} @@ -4496,7 +4499,7 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - es-toolkit@1.46.0: {} + es-toolkit@1.46.1: {} esbuild@0.27.7: optionalDependencies: @@ -4555,15 +4558,15 @@ snapshots: fraction.js@5.3.4: {} - framer-motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + framer-motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: motion-dom: 12.38.0 motion-utils: 12.36.0 tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) fs.realpath@1.0.0: {} @@ -4659,12 +4662,12 @@ snapshots: hast-util-sanitize@5.0.2: dependencies: '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.3.0 + '@ungap/structured-clone': 1.3.1 unist-util-position: 5.0.0 hast-util-to-jsx-runtime@2.3.6: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/hast': 3.0.4 '@types/unist': 3.0.3 comma-separated-tokens: 2.0.3 @@ -4697,11 +4700,11 @@ snapshots: domhandler: 5.0.3 htmlparser2: 10.1.0 - html-react-parser@5.2.17(@types/react@19.2.14)(react@19.2.5): + html-react-parser@5.2.17(@types/react@19.2.14)(react@19.2.6): dependencies: domhandler: 5.0.3 html-dom-parser: 5.1.8 - react: 19.2.5 + react: 19.2.6 react-property: 2.0.2 style-to-js: 1.1.21 optionalDependencies: @@ -4718,7 +4721,7 @@ snapshots: immer@10.2.0: {} - immer@11.1.4: {} + immer@11.1.7: {} immutable@5.1.5: {} @@ -4778,7 +4781,7 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.16.1: + is-core-module@2.16.2: dependencies: hasown: 2.0.3 @@ -4897,9 +4900,9 @@ snapshots: dependencies: uc.micro: 2.1.0 - little-state-machine@4.8.1(react@19.2.5): + little-state-machine@4.8.1(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 load-json-file@4.0.0: dependencies: @@ -5004,7 +5007,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.0 + '@ungap/structured-clone': 1.3.1 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 @@ -5195,18 +5198,18 @@ snapshots: motion-utils@12.36.0: {} - motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) ms@2.1.3: {} - nanoid@3.3.11: {} + nanoid@3.3.12: {} nice-try@1.0.5: {} @@ -5318,9 +5321,9 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.12: + postcss@8.5.14: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -5342,36 +5345,36 @@ snapshots: radash@12.1.1: {} - react-auth-code-input@3.2.1(react@19.2.5): + react-auth-code-input@3.2.1(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 - react-click-away-listener@2.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + react-click-away-listener@2.4.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) - react-dom@19.2.5(react@19.2.5): + react-dom@19.2.6(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 scheduler: 0.27.0 - react-hook-form@7.74.0(react@19.2.5): + react-hook-form@7.75.0(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 - react-hotkeys-hook@5.2.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + react-hotkeys-hook@5.3.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) react-is@16.13.1: {} - react-loading-skeleton@3.5.0(react@19.2.5): + react-loading-skeleton@3.5.0(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 - react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.5): + react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.6): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 @@ -5380,7 +5383,7 @@ snapshots: hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 mdast-util-to-hast: 13.2.1 - react: 19.2.5 + react: 19.2.6 remark-parse: 11.0.0 remark-rehype: 11.1.2 unified: 11.0.5 @@ -5391,47 +5394,47 @@ snapshots: react-property@2.0.2: {} - react-qr-code@2.0.18(react@19.2.5): + react-qr-code@2.0.21(react@19.2.6): dependencies: prop-types: 15.8.1 qr.js: 0.0.0 - react: 19.2.5 + react: 19.2.6 - react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 - react: 19.2.5 - use-sync-external-store: 1.6.0(react@19.2.5) + react: 19.2.6 + use-sync-external-store: 1.6.0(react@19.2.6) optionalDependencies: '@types/react': 19.2.14 redux: 5.0.1 react-refresh@0.18.0: {} - react-router-dom@6.30.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + react-router-dom@6.30.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@remix-run/router': 1.23.2 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) - react-router: 6.30.3(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + react-router: 6.30.3(react@19.2.6) - react-router@6.30.3(react@19.2.5): + react-router@6.30.3(react@19.2.6): dependencies: '@remix-run/router': 1.23.2 - react: 19.2.5 + react: 19.2.6 - react-simple-animate@3.5.3(react-dom@19.2.5(react@19.2.5)): + react-simple-animate@3.5.3(react-dom@19.2.6(react@19.2.6)): dependencies: - react-dom: 19.2.5(react@19.2.5) + react-dom: 19.2.6(react@19.2.6) react-use-websocket@4.13.0: {} - react-virtualized-auto-sizer@1.0.26(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + react-virtualized-auto-sizer@1.0.26(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) - react@19.2.5: {} + react@19.2.6: {} read-pkg@3.0.0: dependencies: @@ -5441,21 +5444,21 @@ snapshots: readdirp@4.1.2: {} - recharts@3.8.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react-is@16.13.1)(react@19.2.5)(redux@5.0.1): + recharts@3.8.1(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react-is@16.13.1)(react@19.2.6)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1))(react@19.2.5) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1))(react@19.2.6) clsx: 2.1.1 decimal.js-light: 2.5.1 - es-toolkit: 1.46.0 + es-toolkit: 1.46.1 eventemitter3: 5.0.4 immer: 10.2.0 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) react-is: 16.13.1 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 - use-sync-external-store: 1.6.0(react@19.2.5) + use-sync-external-store: 1.6.0(react@19.2.6) victory-vendor: 37.3.6 transitivePeerDependencies: - '@types/react' @@ -5518,39 +5521,39 @@ snapshots: resolve@1.22.12: dependencies: es-errors: 1.3.0 - is-core-module: 2.16.1 + is-core-module: 2.16.2 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup@4.60.2: + rollup@4.60.3: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.60.2 - '@rollup/rollup-android-arm64': 4.60.2 - '@rollup/rollup-darwin-arm64': 4.60.2 - '@rollup/rollup-darwin-x64': 4.60.2 - '@rollup/rollup-freebsd-arm64': 4.60.2 - '@rollup/rollup-freebsd-x64': 4.60.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.60.2 - '@rollup/rollup-linux-arm-musleabihf': 4.60.2 - '@rollup/rollup-linux-arm64-gnu': 4.60.2 - '@rollup/rollup-linux-arm64-musl': 4.60.2 - '@rollup/rollup-linux-loong64-gnu': 4.60.2 - '@rollup/rollup-linux-loong64-musl': 4.60.2 - '@rollup/rollup-linux-ppc64-gnu': 4.60.2 - '@rollup/rollup-linux-ppc64-musl': 4.60.2 - '@rollup/rollup-linux-riscv64-gnu': 4.60.2 - '@rollup/rollup-linux-riscv64-musl': 4.60.2 - '@rollup/rollup-linux-s390x-gnu': 4.60.2 - '@rollup/rollup-linux-x64-gnu': 4.60.2 - '@rollup/rollup-linux-x64-musl': 4.60.2 - '@rollup/rollup-openbsd-x64': 4.60.2 - '@rollup/rollup-openharmony-arm64': 4.60.2 - '@rollup/rollup-win32-arm64-msvc': 4.60.2 - '@rollup/rollup-win32-ia32-msvc': 4.60.2 - '@rollup/rollup-win32-x64-gnu': 4.60.2 - '@rollup/rollup-win32-x64-msvc': 4.60.2 + '@rollup/rollup-android-arm-eabi': 4.60.3 + '@rollup/rollup-android-arm64': 4.60.3 + '@rollup/rollup-darwin-arm64': 4.60.3 + '@rollup/rollup-darwin-x64': 4.60.3 + '@rollup/rollup-freebsd-arm64': 4.60.3 + '@rollup/rollup-freebsd-x64': 4.60.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.3 + '@rollup/rollup-linux-arm-musleabihf': 4.60.3 + '@rollup/rollup-linux-arm64-gnu': 4.60.3 + '@rollup/rollup-linux-arm64-musl': 4.60.3 + '@rollup/rollup-linux-loong64-gnu': 4.60.3 + '@rollup/rollup-linux-loong64-musl': 4.60.3 + '@rollup/rollup-linux-ppc64-gnu': 4.60.3 + '@rollup/rollup-linux-ppc64-musl': 4.60.3 + '@rollup/rollup-linux-riscv64-gnu': 4.60.3 + '@rollup/rollup-linux-riscv64-musl': 4.60.3 + '@rollup/rollup-linux-s390x-gnu': 4.60.3 + '@rollup/rollup-linux-x64-gnu': 4.60.3 + '@rollup/rollup-linux-x64-musl': 4.60.3 + '@rollup/rollup-openbsd-x64': 4.60.3 + '@rollup/rollup-openharmony-arm64': 4.60.3 + '@rollup/rollup-win32-arm64-msvc': 4.60.3 + '@rollup/rollup-win32-ia32-msvc': 4.60.3 + '@rollup/rollup-win32-x64-gnu': 4.60.3 + '@rollup/rollup-win32-x64-msvc': 4.60.3 fsevents: 2.3.3 rxjs@7.8.2: @@ -5814,7 +5817,7 @@ snapshots: markdown-it: 14.1.1 minimatch: 10.2.5 typescript: 5.9.3 - yaml: 2.8.3 + yaml: 2.8.4 typesafe-i18n@5.27.1(typescript@5.9.3): dependencies: @@ -5872,20 +5875,20 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - use-breakpoint@4.0.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + use-breakpoint@4.0.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) - use-deep-compare-effect@1.8.1(react@19.2.5): + use-deep-compare-effect@1.8.1(react@19.2.6): dependencies: '@babel/runtime': 7.29.2 dequal: 2.0.3 - react: 19.2.5 + react: 19.2.6 - use-sync-external-store@1.6.0(react@19.2.5): + use-sync-external-store@1.6.0(react@19.2.6): dependencies: - react: 19.2.5 + react: 19.2.6 uuid@8.3.2: {} @@ -5921,19 +5924,19 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.3): + vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4): dependencies: esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - postcss: 8.5.12 - rollup: 4.60.2 + postcss: 8.5.14 + rollup: 4.60.3 tinyglobby: 0.2.16 optionalDependencies: '@types/node': 24.12.2 fsevents: 2.3.3 sass: 1.92.1 - yaml: 2.8.3 + yaml: 2.8.4 which-boxed-primitive@1.1.1: dependencies: @@ -5994,7 +5997,7 @@ snapshots: yaml@1.10.3: {} - yaml@2.8.3: {} + yaml@2.8.4: {} yargs-parser@21.1.1: {} @@ -6010,11 +6013,11 @@ snapshots: zod@3.25.76: {} - zustand@5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5)): + zustand@5.0.13(@types/react@19.2.14)(immer@11.1.7)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)): optionalDependencies: '@types/react': 19.2.14 - immer: 11.1.4 - react: 19.2.5 - use-sync-external-store: 1.6.0(react@19.2.5) + immer: 11.1.7 + react: 19.2.6 + use-sync-external-store: 1.6.0(react@19.2.6) zwitch@2.0.4: {} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 569c556b..55efeff2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -863,9 +863,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.61" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1077,12 +1077,6 @@ dependencies = [ "tiny-keccak", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "cookie" version = "0.18.1" @@ -1236,23 +1230,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cssparser" -version = "0.29.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "matches", - "phf 0.10.1", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - [[package]] name = "cssparser" version = "0.36.0" @@ -1262,7 +1239,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.13.1", + "phf", "smallvec", ] @@ -1278,14 +1255,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" dependencies = [ - "quote", - "syn 2.0.117", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1402,6 +1385,17 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" +[[package]] +name = "dbus" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.61.2", +] + [[package]] name = "defguard-client" version = "1.6.8" @@ -1427,7 +1421,7 @@ dependencies = [ "os_info", "prost", "regex", - "reqwest 0.13.2", + "reqwest 0.13.3", "rust-ini", "semver", "serde", @@ -1436,7 +1430,6 @@ dependencies = [ "sqlx", "struct-patch", "strum", - "swift-rs", "tauri", "tauri-build", "tauri-plugin-clipboard-manager", @@ -1481,7 +1474,7 @@ dependencies = [ "defguard_wireguard_rs", "dirs-next", "prost", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", "thiserror 2.0.18", @@ -1521,9 +1514,9 @@ dependencies = [ [[package]] name = "defguard_wireguard_rs" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6805597cb34bef686b2c3f732ca1f88e6de676d92d43acd632ea5aae5169466" +checksum = "c25476f197cec498e72de55dcaa34f966720ae000eda3171f5144f0433256acc" dependencies = [ "base64 0.22.1", "defguard_boringtun", @@ -1597,19 +1590,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "derive_more" -version = "0.99.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.117", -] - [[package]] name = "derive_more" version = "2.1.1" @@ -1756,12 +1736,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ "bit-set", - "cssparser 0.36.0", + "cssparser", "foldhash 0.2.0", - "html5ever 0.38.0", + "html5ever", "precomputed-hash", - "selectors 0.36.1", - "tendril 0.5.0", + "selectors", + "tendril", ] [[package]] @@ -1800,6 +1780,21 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dunce" version = "1.0.5" @@ -1966,23 +1961,9 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fax" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" [[package]] name = "fdeflate" @@ -2142,13 +2123,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] -name = "futf" -version = "0.1.5" +name = "futures" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ - "mac", - "new_debug_unreachable", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] @@ -2237,6 +2223,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -2247,15 +2234,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gdk" version = "0.18.2" @@ -2375,17 +2353,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -2395,7 +2362,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -2612,9 +2579,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -2668,9 +2635,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" @@ -2732,18 +2699,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "html5ever" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" -dependencies = [ - "log", - "mac", - "markup5ever 0.14.1", - "match_token", -] - [[package]] name = "html5ever" version = "0.38.0" @@ -2751,7 +2706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "markup5ever 0.38.0", + "markup5ever", ] [[package]] @@ -3032,9 +2987,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -3072,7 +3027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -3123,16 +3078,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is-docker" version = "0.2.0" @@ -3282,9 +3227,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -3334,18 +3279,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "kuchikiki" -version = "0.8.8-speedreader" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" -dependencies = [ - "cssparser 0.29.6", - "html5ever 0.29.1", - "indexmap 2.14.0", - "selectors 0.24.0", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -3400,11 +3333,20 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] + [[package]] name = "libgit2-sys" -version = "0.18.3+1.9.2" +version = "0.18.4+1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +checksum = "9b26f66f35e1871b22efcf7191564123d2a446ca0538cde63c23adfefa9b15b7" dependencies = [ "cc", "libc", @@ -3447,7 +3389,7 @@ dependencies = [ "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.4", + "redox_syscall 0.7.5", ] [[package]] @@ -3516,12 +3458,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - [[package]] name = "mac-notification-sys" version = "0.6.12" @@ -3534,20 +3470,6 @@ dependencies = [ "time", ] -[[package]] -name = "markup5ever" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" -dependencies = [ - "log", - "phf 0.11.3", - "phf_codegen 0.11.3", - "string_cache 0.8.9", - "string_cache_codegen 0.5.4", - "tendril 0.4.3", -] - [[package]] name = "markup5ever" version = "0.38.0" @@ -3555,21 +3477,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" dependencies = [ "log", - "tendril 0.5.0", + "tendril", "web_atoms", ] -[[package]] -name = "match_token" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "matchers" version = "0.2.0" @@ -3579,12 +3490,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.8.4" @@ -3645,7 +3550,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.61.2", ] @@ -3661,9 +3566,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.17.2" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177" +checksum = "0ae8844f63b5b118e334e205585b8c5c17b984121dbdb179d44aeb087ffad3cb" dependencies = [ "crossbeam-channel", "dpi", @@ -3674,10 +3579,10 @@ dependencies = [ "objc2-core-foundation", "objc2-foundation 0.3.2", "once_cell", - "png 0.17.16", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3753,9 +3658,9 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9854ea6ad14e3f4698a7f03b65bce0833dd2d81d594a0e4a984170537146b6" +checksum = "be8919612f6028ab4eacbbfe1234a9a43e3722c6e0915e7ff519066991905092" dependencies = [ "bitflags 2.11.1", "libc", @@ -3776,9 +3681,9 @@ dependencies = [ [[package]] name = "netlink-packet-wireguard" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037892b0e01ce41f30398a47be2051e712a2cf1eed9cb7e5e6a92b05c423255b" +checksum = "205d2bad950c9cbbbf08cc5432d6501edfe02d3a34ecad822a3e91c98e97dbf6" dependencies = [ "libc", "log", @@ -3828,12 +3733,6 @@ dependencies = [ "memoffset", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nom" version = "7.1.3" @@ -3855,9 +3754,9 @@ dependencies = [ [[package]] name = "notify-rust" -version = "4.16.0" +version = "4.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e551a9f0db223eaf3eb156906f99f46897fd951ee66dd1cb0be14db4d36d2fa" +checksum = "50ff2e74231b72c832d82982193b417f230945be6bdb5575b251d941d31adb00" dependencies = [ "futures-lite", "log", @@ -3867,6 +3766,15 @@ dependencies = [ "zbus", ] +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -4116,6 +4024,16 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "objc2-io-surface" version = "0.3.2" @@ -4241,15 +4159,14 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.78" +version = "0.10.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" dependencies = [ "bitflags 2.11.1", "cfg-if", "foreign-types 0.3.2", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -4282,9 +4199,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.114" +version = "0.9.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" dependencies = [ "cc", "libc", @@ -4443,105 +4360,25 @@ dependencies = [ "indexmap 2.14.0", ] -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_shared 0.8.0", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros 0.11.3", - "phf_shared 0.11.3", -] - [[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_macros 0.13.1", - "phf_shared 0.13.1", + "phf_macros", + "phf_shared", "serde", ] -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", -] - [[package]] name = "phf_codegen" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.6", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.6", + "phf_generator", + "phf_shared", ] [[package]] @@ -4551,34 +4388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", - "syn 2.0.117", + "phf_shared", ] [[package]] @@ -4587,63 +4397,36 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", + "phf_generator", + "phf_shared", "proc-macro2", "quote", "syn 2.0.117", ] -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher 1.0.2", -] - [[package]] name = "phf_shared" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ - "siphasher 1.0.2", + "siphasher", ] [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" dependencies = [ "proc-macro2", "quote", @@ -4714,7 +4497,7 @@ checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" dependencies = [ "base64 0.22.1", "indexmap 2.14.0", - "quick-xml 0.39.2", + "quick-xml 0.39.4", "serde", "time", ] @@ -4770,6 +4553,15 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "posture" +version = "1.6.8" +dependencies = [ + "serde", + "sysinfo", + "wmi", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -4863,12 +4655,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.106" @@ -5010,9 +4796,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.39.2" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] @@ -5100,20 +4886,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - [[package]] name = "rand" version = "0.8.6" @@ -5135,16 +4907,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -5165,15 +4927,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - [[package]] name = "rand_core" version = "0.6.4" @@ -5192,24 +4945,6 @@ dependencies = [ "getrandom 0.3.4", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -5227,9 +4962,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ "bitflags 2.11.1", ] @@ -5362,9 +5097,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -5507,9 +5242,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.41.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" dependencies = [ "arrayvec", "borsh", @@ -5552,9 +5287,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.39" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", @@ -5590,13 +5325,13 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni 0.21.1", + "jni 0.22.4", "log", "once_cell", "rustls", @@ -5763,24 +5498,6 @@ dependencies = [ "libc", ] -[[package]] -name = "selectors" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" -dependencies = [ - "bitflags 1.3.2", - "cssparser 0.29.6", - "derive_more 0.99.20", - "fxhash", - "log", - "phf 0.8.0", - "phf_codegen 0.8.0", - "precomputed-hash", - "servo_arc 0.2.0", - "smallvec", -] - [[package]] name = "selectors" version = "0.36.1" @@ -5788,15 +5505,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ "bitflags 2.11.1", - "cssparser 0.36.0", - "derive_more 2.1.1", + "cssparser", + "derive_more", "log", "new_debug_unreachable", - "phf 0.13.1", - "phf_codegen 0.13.1", + "phf", + "phf_codegen", "precomputed-hash", "rustc-hash", - "servo_arc 0.4.3", + "servo_arc", "smallvec", ] @@ -5919,9 +5636,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.18.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +checksum = "f05839ce67618e14a09b286535c0d9c94e85ef25469b0e13cb4f844e5593eb19" dependencies = [ "base64 0.22.1", "chrono", @@ -5938,9 +5655,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.18.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +checksum = "cf2ebbe86054f9b45bc3881e865683ccfaccce97b9b4cb53f3039d67f355a334" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -5970,16 +5687,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "servo_arc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - [[package]] name = "servo_arc" version = "0.4.3" @@ -6070,15 +5777,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" @@ -6386,19 +6087,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "string_cache" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" -dependencies = [ - "new_debug_unreachable", - "parking_lot", - "phf_shared 0.11.3", - "precomputed-hash", - "serde", -] - [[package]] name = "string_cache" version = "0.9.0" @@ -6407,30 +6095,18 @@ checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared 0.13.1", + "phf_shared", "precomputed-hash", ] -[[package]] -name = "string_cache_codegen" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", -] - [[package]] name = "string_cache_codegen" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -6454,18 +6130,18 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "struct-patch" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d4caaaccd69c9b56c5f5b33d4dca462464d3275230e4d2d3739ba6d4bf5bcb" +checksum = "b6647f17706475257679fb9a4a71d85b222633d398d685010d7cc2f4c99de375" dependencies = [ "struct-patch-derive", ] [[package]] name = "struct-patch-derive" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1671c6f0992b1b4cb4f5f8ea4a58f9a5f7f895a7638ef9690633dcec0aa67944" +checksum = "203b436d4379c929ff3e7340b89c3a57ca3be8a76b3376448176575e8ca3f258" dependencies = [ "proc-macro2", "quote", @@ -6567,6 +6243,20 @@ dependencies = [ "libc", ] +[[package]] +name = "sysinfo" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9f9fe3d2b7b75cf4f2805e5b9926e8ac47146667b16b86298c4a8bf08cc469" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.62.2", +] + [[package]] name = "system-configuration" version = "0.7.0" @@ -6603,15 +6293,16 @@ dependencies = [ [[package]] name = "tao" -version = "0.34.8" +version = "0.35.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" +checksum = "a33f7f9e486ade65fcf1e45c440f9236c904f5c1002cdc7fc6ae582777345ce4" dependencies = [ "bitflags 2.11.1", "block2 0.6.2", "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", + "dbus", "dispatch2", "dlopen2", "dpi", @@ -6622,13 +6313,14 @@ dependencies = [ "libc", "log", "ndk", - "ndk-context", "ndk-sys", "objc2 0.6.4", "objc2-app-kit", "objc2-foundation 0.3.2", + "objc2-ui-kit", "once_cell", "parking_lot", + "percent-encoding", "raw-window-handle", "tao-macros", "unicode-segmentation", @@ -6664,9 +6356,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.10.3" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da77cc00fb9028caf5b5d4650f75e31f1ef3693459dfca7f7e506d1ecef0ba2d" +checksum = "b93bd86d231f0a8138f11a02a584769fe4b703dc36ae133d783228dbc4801405" dependencies = [ "anyhow", "bytes", @@ -6693,7 +6385,7 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", "serde_repr", @@ -6716,9 +6408,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.5.6" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bbc990d1dbf57a8e1c7fa2327f2a614d8b757805603c1b9ba5c81bade09fd4d" +checksum = "3a318b234cc2dea65f575467bafcfb76286bce228ebc3778e337d61d03213007" dependencies = [ "anyhow", "cargo_toml", @@ -6732,15 +6424,14 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.9.12+spec-1.1.0", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.5.5" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a24476afd977c5d5d169f72425868613d82747916dd29e0a357c84c4bd6d29" +checksum = "6bd11644962add2549a60b7e7c6800f17d7020156e02f516021d8103e80cc528" dependencies = [ "base64 0.22.1", "brotli", @@ -6765,9 +6456,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.5.5" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39b349a98dadaffebb73f0a40dcd1f23c999211e5a2e744403db384d0c33de7" +checksum = "fed9d3742a37a355d2e47c9af924e9fbc112abb76f9835d35d4780e318419502" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -6779,9 +6470,9 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.5.4" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddde7d51c907b940fb573006cdda9a642d6a7c8153657e88f8a5c3c9290cd4aa" +checksum = "eefb2c18e8a605c23edb48fc56bb77381199e1a1e7f6ff0c9b970afe7b3cb8ee" dependencies = [ "anyhow", "glob", @@ -6790,7 +6481,6 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "toml 0.9.12+spec-1.1.0", "walkdir", ] @@ -6811,9 +6501,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.4.7" +version = "2.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94deb2e2e4641514ac496db2cddcfc850d6fc9d51ea17b82292a0490bd20ba5b" +checksum = "70ee75bc5627f77bfdf40c913255ebc258117b10ebe2b2239a1a1cf40b0b58aa" dependencies = [ "dunce", "plist", @@ -6832,9 +6522,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa4150c95ae391946cc8b8f905ab14797427caba3a8a2f79628e956da91809" +checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884" dependencies = [ "log", "raw-window-handle", @@ -6850,9 +6540,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36e1ec28b79f3d0683f4507e1615c36292c0ea6716668770d4396b9b39871ed8" +checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371" dependencies = [ "anyhow", "dunce", @@ -6868,15 +6558,15 @@ dependencies = [ "tauri-plugin", "tauri-utils", "thiserror 2.0.18", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "url", ] [[package]] name = "tauri-plugin-http" -version = "2.5.8" +version = "2.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfba7d4ec72763f9d1fdf73c217747f01e2c84b08b87a8cacd2f94f35853f84d" +checksum = "b5bd512048e1985b7ec78f96d99083e2ddaf7e0d906b2b63c44ce5bb8b894067" dependencies = [ "bytes", "cookie_store", @@ -6939,9 +6629,9 @@ dependencies = [ [[package]] name = "tauri-plugin-opener" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc624469b06f59f5a29f874bbc61a2ed737c0f9c23ef09855a292c389c42e83f" +checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29" dependencies = [ "dunce", "glob", @@ -6989,9 +6679,9 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc61e4822b8f74d68278e09161d3e3fdd1b14b9eb781e24edccaabf10c420e8c" +checksum = "5c8f29386f5e9fdc699182388a33ee80a56de436d91b67459e86afef426282af" dependencies = [ "serde", "serde_json", @@ -7020,9 +6710,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.10.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2826d79a3297ed08cd6ea7f412644ef58e32969504bc4fbd8d7dbeabc4445ea2" +checksum = "8fef478ba1d2ac21c2d528740b24d0cb315e1e8b1111aae53fafac34804371fc" dependencies = [ "cookie", "dpi", @@ -7045,9 +6735,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.10.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11ea2e6f801d275fdd890d6c9603736012742a1c33b96d0db788c9cdebf7f9e" +checksum = "a3989df2ae1c476404fe0a2e8ffc4cfbde97e51efd613c2bb5355fbc9ab52cf0" dependencies = [ "gtk", "http", @@ -7071,24 +6761,24 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.8.3" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219a1f983a2af3653f75b5747f76733b0da7ff03069c7a41901a5eb3ace4557d" +checksum = "d57200389a2f82b4b0a40ae29ca19b6978116e8f4d4e974c3234ce40c0ffbdec" dependencies = [ "anyhow", "brotli", "cargo_metadata", "ctor", + "dom_query", "dunce", "glob", - "html5ever 0.29.1", "http", "infer", "json-patch", - "kuchikiki", "log", "memchr", - "phf 0.11.3", + "phf", + "plist", "proc-macro2", "quote", "regex", @@ -7100,7 +6790,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.18", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "url", "urlpattern", "uuid", @@ -7143,17 +6833,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - [[package]] name = "tendril" version = "0.5.0" @@ -7305,9 +6984,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -7497,9 +7176,9 @@ checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", @@ -7529,9 +7208,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -7541,9 +7220,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost", @@ -7552,9 +7231,9 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -7587,20 +7266,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51" dependencies = [ "bitflags 2.11.1", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -7705,9 +7384,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.21.3" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" +checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" dependencies = [ "crossbeam-channel", "dirs", @@ -7719,10 +7398,10 @@ dependencies = [ "objc2-core-graphics", "objc2-foundation 0.3.2", "once_cell", - "png 0.17.16", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7954,7 +7633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "431d2f443e7828a6c29d188de98b6771a6491ee98bba2d4372643bf93f988a18" dependencies = [ "anyhow", - "siphasher 1.0.2", + "siphasher", "uniffi_internal_macros", "uniffi_pipeline", ] @@ -8169,12 +7848,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -8207,9 +7880,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -8220,9 +7893,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -8230,9 +7903,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8240,9 +7913,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -8253,9 +7926,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -8364,7 +8037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" dependencies = [ "proc-macro2", - "quick-xml 0.39.2", + "quick-xml 0.39.4", "quote", ] @@ -8379,9 +8052,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -8403,10 +8076,10 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" dependencies = [ - "phf 0.13.1", - "phf_codegen 0.13.1", - "string_cache 0.9.0", - "string_cache_codegen 0.6.1", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", ] [[package]] @@ -8805,13 +8478,13 @@ dependencies = [ [[package]] name = "windows-service" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193cae8e647981c35bc947fdd57ba7928b1fa0d4a79305f6dd2dc55221ac35ac" +checksum = "857224b3b211c6f3616921f081ee54721ee3ad2ace2fac6a6337e032f7b4dcf2" dependencies = [ "bitflags 2.11.1", "widestring 1.2.1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9331,6 +9004,20 @@ dependencies = [ "wayland-protocols-wlr", ] +[[package]] +name = "wmi" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c81b85c57a57500e56669586496bf2abd5cf082b9d32995251185d105208b64" +dependencies = [ + "futures", + "log", + "serde", + "thiserror 2.0.18", + "windows 0.62.2", + "windows-core 0.62.2", +] + [[package]] name = "writeable" version = "0.6.3" @@ -9339,9 +9026,9 @@ checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wry" -version = "0.54.4" +version = "0.55.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a8135d8676225e5744de000d4dff5a082501bf7db6a1c1495034f8c314edbc" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" dependencies = [ "base64 0.22.1", "block2 0.6.2", @@ -9641,9 +9328,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.10.1" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db0ecb8987cf5e92653c57c098f7f0e39a03112edb796f4fe089fb7eaa14ff" +checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" dependencies = [ "endi", "enumflags2", @@ -9656,9 +9343,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.10.1" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b949b639ab1b4bed763aa7481ba0e368af68d8b55532f8ed4bec86a59f2ca98" +checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9cb9ddba..cea595f8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["cli", "common"] +members = ["cli", "common", "posture"] default-members = [".", "cli"] [workspace.dependencies] @@ -30,7 +30,7 @@ authors = ["Defguard"] edition = "2021" homepage = "https://github.com/DefGuard/client" license-file = "../LICENSE.md" -rust-version = "1.87" +rust-version = "1.95" version = "1.6.8" [package] @@ -84,7 +84,7 @@ sqlx = { version = "0.8", features = [ "uuid", "macros", ] } -struct-patch = "0.10" +struct-patch = "0.11" strum = { version = "0.28", features = ["derive"] } tauri = { version = "2", features = [ "native-tls-vendored", @@ -128,9 +128,6 @@ objc2 = "0.6" objc2-foundation = "0.3" objc2-network-extension = "0.3" -[target.'cfg(target_os = "macos")'.build-dependencies] -swift-rs = { version = "1.0", features = ["build"] } - [target.'cfg(unix)'.dependencies] nix = { version = "0.31", features = ["user", "fs"] } tokio-stream = "0.1" diff --git a/src-tauri/posture/Cargo.toml b/src-tauri/posture/Cargo.toml new file mode 100644 index 00000000..54639972 --- /dev/null +++ b/src-tauri/posture/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "posture" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +rust-version.workspace = true +version.workspace = true + +[dependencies] +sysinfo = {version = "0.39", default-features = false, features = ["apple-app-store", "system"]} + +[target.'cfg(windows)'.dependencies] +serde.workspace = true +wmi = {version = "0.18", default-features = false} diff --git a/src-tauri/posture/src/inspector/linux.rs b/src-tauri/posture/src/inspector/linux.rs new file mode 100644 index 00000000..dd6ccc25 --- /dev/null +++ b/src-tauri/posture/src/inspector/linux.rs @@ -0,0 +1,25 @@ +use std::process::Command; + +/// Determine if any block device has "crypto_LUKS" type. +fn check_luks() -> Result { + let output = Command::new("lsblk") + .args(["-o", "NAME,FSTYPE,TYPE"]) + .output() + .map_err(|_| ())?; + + if !output.status.success() { + return Err(()); + } + + Ok(false) +} + +// https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 +pub fn disk_encryption_status() -> Result { + // TODO: zfs encryption + Err(InspectionError::NotApplicable) +} + +pub(crate) fn anti_virus_status() -> Result { + Err(InspectionError::NotApplicable) +} diff --git a/src-tauri/posture/src/inspector/macos.rs b/src-tauri/posture/src/inspector/macos.rs new file mode 100644 index 00000000..68b76ccb --- /dev/null +++ b/src-tauri/posture/src/inspector/macos.rs @@ -0,0 +1,17 @@ +use std::process::Command; + +use crate::InspectionError; + +pub(crate) fn disk_encryption_status() -> Result { + let output = Command::new("fdesetup") + .arg("isactive") + .output() + .map_err(|_| InspectionError::DetectionFailed)?; + let stdout = String::from_utf8_lossy(&output.stdout); + + Ok(stdout.trim_end() == "true") +} + +pub(crate) fn anti_virus_status() -> Result { + Err(InspectionError::NotApplicable) +} diff --git a/src-tauri/posture/src/inspector/mod.rs b/src-tauri/posture/src/inspector/mod.rs new file mode 100644 index 00000000..75d31d0c --- /dev/null +++ b/src-tauri/posture/src/inspector/mod.rs @@ -0,0 +1,6 @@ +#[cfg(target_os = "linux")] +pub(crate) mod linux; +#[cfg(target_os = "macos")] +pub(crate) mod macos; +#[cfg(windows)] +pub(crate) mod windows; diff --git a/src-tauri/posture/src/inspector/windows.rs b/src-tauri/posture/src/inspector/windows.rs new file mode 100644 index 00000000..0681f65d --- /dev/null +++ b/src-tauri/posture/src/inspector/windows.rs @@ -0,0 +1,118 @@ +// TODO: use `async_raw_query` + +use serde::Deserialize; + +use wmi::{WMIConnection, WMIError}; + +use crate::InspectionError; + +#[derive(Deserialize)] +#[serde(rename = "Win32_EncryptableVolume")] +#[serde(rename_all = "PascalCase")] +struct Win32EncryptableVolume { + // drive_letter: Option, + // 0 = unprotected, 1 = protected, 2 = unknown + protection_status: u32, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct AntiVirusProduct { + // display_name: String, + product_state: u32, +} + +#[derive(Deserialize)] +#[serde(rename = "Win32_ComputerSystem")] +#[serde(rename_all = "PascalCase")] +struct Win32ComputerSystem { + // domain: String, + part_of_domain: bool, +} + +/// This requires Administrator access, and only detects BitLocker for drive C:. +/// +/// Equivalent to PowerShell command: +/// `Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftVolumeEncryption" -query "SELECT * FROM Win32_EncryptableVolume"` +pub(crate) fn disk_encryption_status() -> Result { + let conn = + WMIConnection::with_namespace_path("root\\CIMV2\\Security\\MicrosoftVolumeEncryption") + .map_err(|err| { + if let WMIError::HResultError { .. } = err { + InspectionError::PermissionDenied + } else { + InspectionError::DetectionFailed + } + })?; + + let volumes: Vec = conn + .raw_query("SELECT ProtectionStatus FROM Win32_EncryptableVolume WHERE DriveLetter='C:'") + .map_err(|_| InspectionError::DetectionFailed)?; + + match volumes.first() { + Some(vol) => { + return match vol.protection_status { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(InspectionError::DetectionFailed), + }; + } + None => Err(InspectionError::DetectionFailed), + } +} + +/// Determine AntiVirus status. +/// +/// Check manually in PowerShell: +/// `Get-CimInstance -Namespace root\SecurityCenter2 -ClassName AntivirusProduct` +/// +/// Equivalent to PowerShell command: +/// `Get-WmiObject -Namespace "root\SecurityCenter2" -query "SELECT * FROM AntiVirusProduct"` +pub(crate) fn anti_virus_status() -> Result { + let conn = WMIConnection::with_namespace_path("root\\SecurityCenter2").map_err(|err| { + if let WMIError::HResultError { .. } = err { + InspectionError::PermissionDenied + } else { + InspectionError::DetectionFailed + } + })?; + + let products: Vec = + conn.query().map_err(|_| InspectionError::DetectionFailed)?; + + if products.is_empty() { + return Ok(false); + } + + for product in products { + let enabled = (product.product_state & 0x0001_0000) != 0; + let realtime = (product.product_state & 0x0002_0000) != 0; + // let up_to_date = (product.product_state & 0x0004_0000) != 0; + if enabled || realtime { + return Ok(true); + } + } + + Ok(false) +} + +/// Check manually in PowerShell: +/// `Get-CimInstance -ClassName Win32_ComputerSystem` +/// +/// Equivalent to PowerShell command: +/// `Get-WmiObject -query "SELECT * FROM Win32_ComputerSystem"` +pub(crate) fn part_of_domain() -> Result { + let conn = WMIConnection::new().map_err(|err| { + if let WMIError::HResultError { .. } = err { + InspectionError::PermissionDenied + } else { + InspectionError::DetectionFailed + } + })?; + + let system = conn + .get::() + .map_err(|_| InspectionError::DetectionFailed)?; + + Ok(system.part_of_domain) +} diff --git a/src-tauri/posture/src/lib.rs b/src-tauri/posture/src/lib.rs new file mode 100644 index 00000000..6087219a --- /dev/null +++ b/src-tauri/posture/src/lib.rs @@ -0,0 +1,129 @@ +mod inspector; +#[cfg(test)] +mod tests; + +use std::{error::Error, fmt}; + +use sysinfo::System; + +#[derive(Debug)] +pub enum InspectionError { + DetectionFailed, + NotApplicable, + PermissionDenied, +} + +impl fmt::Display for InspectionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::DetectionFailed => f.write_str("detection failed"), + Self::NotApplicable => f.write_str("not applicable on this platform"), + Self::PermissionDenied => f.write_str("permission denied"), + } + } +} + +impl Error for InspectionError {} + +pub enum OsType { + MacOS, + FreeBSD, + Linux, + NetBSD, + Windows, +} + +impl OsType { + /// Returns OS type for the running machine. + /// Note: Unsupported machines won't compile. + pub fn this_machine() -> Self { + #[cfg(target_os = "macos")] + { + Self::MacOS + } + #[cfg(target_os = "freebsd")] + { + Self::FreeBSD + } + #[cfg(target_os = "linux")] + { + Self::Linux + } + #[cfg(target_os = "netbsd")] + { + Self::NetBSD + } + #[cfg(windows)] + { + Self::Windows + } + } +} + +pub fn os_type() -> OsType { + OsType::this_machine() +} + +pub fn os_name() -> Result { + System::name().ok_or_else(|| InspectionError::DetectionFailed) +} + +pub fn os_version() -> Result { + #[cfg(target_os = "linux")] + { + System::kernel_version().ok_or_else(|| InspectionError::DetectionFailed) + } + + #[cfg(not(target_os = "linux"))] + { + System::os_version().ok_or_else(|| InspectionError::DetectionFailed) + } +} + +pub fn disk_encryption_status() -> Result { + #[cfg(target_os = "macos")] + { + inspector::macos::disk_encryption_status() + } + + #[cfg(windows)] + { + inspector::windows::disk_encryption_status() + } + + #[cfg(target_os = "linux")] + // XXX + { + Err(InspectionError::NotApplicable) + } +} + +pub fn anti_virus_status() -> Result { + #[cfg(target_os = "macos")] + { + inspector::macos::anti_virus_status() + } + + #[cfg(windows)] + { + inspector::windows::anti_virus_status() + } + + #[cfg(target_os = "linux")] + // XXX + { + Err(InspectionError::NotApplicable) + } +} + +pub fn part_of_domain() -> Result { + #[cfg(windows)] + { + inspector::windows::part_of_domain() + } + + #[cfg(not(windows))] + { + Err(InspectionError::NotApplicable) + } +} diff --git a/src-tauri/posture/src/tests/linux.rs b/src-tauri/posture/src/tests/linux.rs new file mode 100644 index 00000000..3290cf77 --- /dev/null +++ b/src-tauri/posture/src/tests/linux.rs @@ -0,0 +1,16 @@ +use crate::{os_name, os_type, OsType}; + +#[test] +fn test_os_type() { + assert!(matches!(os_type(), OsType::Linux)); +} + +#[test] +fn test_os_name() { + assert!(os_name().unwrap().ends_with("Linux")); +} + +#[test] +fn test_os_version() { + assert!(os_version().is_ok()); +} diff --git a/src-tauri/posture/src/tests/macos.rs b/src-tauri/posture/src/tests/macos.rs new file mode 100644 index 00000000..8dcd1e4b --- /dev/null +++ b/src-tauri/posture/src/tests/macos.rs @@ -0,0 +1,21 @@ +use crate::{disk_encryption_status, os_name, os_type, os_version, OsType}; + +#[test] +fn test_os_type() { + assert!(matches!(os_type(), OsType::MacOS)); +} + +#[test] +fn test_os_name() { + assert_eq!(os_name().unwrap(), "Darwin"); +} + +#[test] +fn test_os_version() { + assert!(os_version().is_ok()); +} + +#[test] +fn test_disk_encryption() { + assert!(disk_encryption_status().unwrap()); +} diff --git a/src-tauri/posture/src/tests/mod.rs b/src-tauri/posture/src/tests/mod.rs new file mode 100644 index 00000000..0337daa1 --- /dev/null +++ b/src-tauri/posture/src/tests/mod.rs @@ -0,0 +1,6 @@ +#[cfg(target_os = "linux")] +mod linux; +#[cfg(target_os = "macos")] +mod macos; +#[cfg(windows)] +mod windows; diff --git a/src-tauri/posture/src/tests/windows.rs b/src-tauri/posture/src/tests/windows.rs new file mode 100644 index 00000000..8921a7a6 --- /dev/null +++ b/src-tauri/posture/src/tests/windows.rs @@ -0,0 +1,33 @@ +use crate::{ + anti_virus_status, disk_encryption_status, os_name, os_type, os_version, part_of_domain, OsType, +}; + +#[test] +fn test_os_type() { + assert!(matches!(os_type(), OsType::Windows)); +} + +#[test] +fn test_os_name() { + assert_eq!(os_name().unwrap(), "Windows"); +} + +#[test] +fn test_os_version() { + assert!(os_version().is_ok()); +} + +#[test] +fn test_disk_encryption() { + assert!(!disk_encryption_status().unwrap()); +} + +#[test] +fn test_anti_virus() { + assert!(anti_virus_status().unwrap()); +} + +#[test] +fn test_part_of_domain() { + assert!(!part_of_domain().unwrap()); +} From 93991895217e831ea038f535fffec6b969020c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Mon, 11 May 2026 10:51:13 +0200 Subject: [PATCH 02/11] Update protos --- src-tauri/Cargo.lock | 45 ++++++++-------- src-tauri/Cargo.toml | 4 +- src-tauri/build.rs | 9 +++- src-tauri/cli/build.rs | 2 +- src-tauri/cli/src/bin/dg.rs | 51 +++++++++++++------ src-tauri/posture/Cargo.toml | 15 ------ src-tauri/posture/src/inspector/mod.rs | 6 --- src-tauri/proto | 2 +- src-tauri/src/commands.rs | 2 +- src-tauri/src/database/models/instance.rs | 12 ++--- src-tauri/src/database/models/location.rs | 2 +- .../src => src/enterprise}/inspector/linux.rs | 0 .../src => src/enterprise}/inspector/macos.rs | 6 +-- .../enterprise/inspector/mod.rs} | 23 ++++----- .../enterprise/inspector}/tests/linux.rs | 0 .../enterprise/inspector}/tests/macos.rs | 2 +- .../enterprise/inspector}/tests/mod.rs | 0 .../enterprise/inspector}/tests/windows.rs | 0 .../enterprise}/inspector/windows.rs | 4 +- src-tauri/src/enterprise/mod.rs | 1 + src-tauri/src/enterprise/periodic/config.rs | 4 +- src-tauri/src/proto.rs | 22 +++++++- src-tauri/src/service/mod.rs | 2 +- src-tauri/src/utils.rs | 2 +- 24 files changed, 122 insertions(+), 94 deletions(-) delete mode 100644 src-tauri/posture/Cargo.toml delete mode 100644 src-tauri/posture/src/inspector/mod.rs rename src-tauri/{posture/src => src/enterprise}/inspector/linux.rs (100%) rename src-tauri/{posture/src => src/enterprise}/inspector/macos.rs (70%) rename src-tauri/{posture/src/lib.rs => src/enterprise/inspector/mod.rs} (86%) rename src-tauri/{posture/src => src/enterprise/inspector}/tests/linux.rs (100%) rename src-tauri/{posture/src => src/enterprise/inspector}/tests/macos.rs (79%) rename src-tauri/{posture/src => src/enterprise/inspector}/tests/mod.rs (100%) rename src-tauri/{posture/src => src/enterprise/inspector}/tests/windows.rs (100%) rename src-tauri/{posture/src => src/enterprise}/inspector/windows.rs (97%) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 55efeff2..df441f76 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -727,6 +727,15 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -1039,7 +1048,7 @@ dependencies = [ name = "common" version = "1.6.8" dependencies = [ - "nix 0.31.2", + "nix 0.31.3", ] [[package]] @@ -1414,7 +1423,7 @@ dependencies = [ "hyper-util", "known-folders", "log", - "nix 0.31.2", + "nix 0.31.3", "objc2 0.6.4", "objc2-foundation 0.3.2", "objc2-network-extension", @@ -1430,6 +1439,7 @@ dependencies = [ "sqlx", "struct-patch", "strum", + "sysinfo", "tauri", "tauri-build", "tauri-plugin-clipboard-manager", @@ -1462,6 +1472,7 @@ dependencies = [ "windows-acl", "windows-service", "windows-sys 0.61.2", + "wmi", "x25519-dalek", ] @@ -1501,7 +1512,7 @@ dependencies = [ "ip_network", "ip_network_table", "libc", - "nix 0.31.2", + "nix 0.31.3", "parking_lot", "ring", "socket2", @@ -1529,7 +1540,7 @@ dependencies = [ "netlink-packet-utils", "netlink-packet-wireguard", "netlink-sys", - "nix 0.31.2", + "nix 0.31.3", "regex", "serde", "thiserror 2.0.18", @@ -3722,9 +3733,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags 2.11.1", "cfg-if", @@ -4553,15 +4564,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "posture" -version = "1.6.8" -dependencies = [ - "serde", - "sysinfo", - "wmi", -] - [[package]] name = "potential_utf" version = "0.1.5" @@ -5636,11 +5638,12 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.19.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05839ce67618e14a09b286535c0d9c94e85ef25469b0e13cb4f844e5593eb19" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", @@ -5655,9 +5658,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.19.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2ebbe86054f9b45bc3881e865683ccfaccce97b9b4cb53f3039d67f355a334" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -6245,9 +6248,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.39.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9f9fe3d2b7b75cf4f2805e5b9926e8ac47146667b16b86298c4a8bf08cc469" +checksum = "a4deba334e1190ba7cb498327affa11e5ece10d26a30ab2f27fcf09504b8d8b6" dependencies = [ "libc", "memchr", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cea595f8..66da9a35 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["cli", "common", "posture"] +members = ["cli", "common"] default-members = [".", "cli"] [workspace.dependencies] @@ -86,6 +86,7 @@ sqlx = { version = "0.8", features = [ ] } struct-patch = "0.11" strum = { version = "0.28", features = ["derive"] } +sysinfo = {version = "0.39", default-features = false, features = ["apple-app-store", "system"]} tauri = { version = "2", features = [ "native-tls-vendored", "image-png", @@ -161,6 +162,7 @@ windows-sys = { version = "0.61", features = [ # Network address change notifications (NotifyAddrChange) "Win32_NetworkManagement_IpHelper", ] } +wmi = {version = "0.18", default-features = false} [features] # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 91455f0e..e38786b2 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -17,8 +17,13 @@ fn main() -> Result<(), Box> { // Make all messages serde-serializable. .type_attribute(".", "#[derive(serde::Serialize,serde::Deserialize)]") .compile_protos( - &["proto/client/client.proto", "proto/core/proxy.proto"], - &["proto/client", "proto/core"], + &[ + "proto/v1/client/client.proto", + "proto/v1/core/proxy.proto", + "proto/enterprise/v2/posture/posture.proto", + "proto/common/client_types.proto", + ], + &["proto"], )?; tauri_build::build(); diff --git a/src-tauri/cli/build.rs b/src-tauri/cli/build.rs index fb4ca05e..a25227de 100644 --- a/src-tauri/cli/build.rs +++ b/src-tauri/cli/build.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), Box> { ) // Make all messages serde-serializable. .type_attribute(".", "#[derive(serde::Deserialize,serde::Serialize)]") - .compile_protos(&["../proto/core/proxy.proto"], &["../proto/core"])?; + .compile_protos(&["../proto/v1/core/proxy.proto"], &["../proto"])?; Ok(()) } diff --git a/src-tauri/cli/src/bin/dg.rs b/src-tauri/cli/src/bin/dg.rs index 13c20b7e..d3edc4ce 100644 --- a/src-tauri/cli/src/bin/dg.rs +++ b/src-tauri/cli/src/bin/dg.rs @@ -19,6 +19,10 @@ use defguard_wireguard_rs::{ error::WireguardInterfaceError, key::Key, net::IpAddrMask, peer::Peer, InterfaceConfiguration, WGApi, WireguardInterfaceApi, }; +use proto::defguard::client_types::{ + Device, DeviceConfig, DeviceConfigResponse, EnrollmentStartRequest, EnrollmentStartResponse, + InstanceInfo, InstanceInfoRequest, InstanceInfoResponse, NewDevice, +}; use reqwest::{Client, StatusCode, Url}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -31,15 +35,36 @@ use tracing::{debug, error, info, level_filters::LevelFilter, trace, warn}; use tracing_subscriber::EnvFilter; mod proto { - include!(concat!(env!("OUT_DIR"), "/defguard.proxy.rs")); + pub mod defguard { + pub mod client_types { + include!(concat!(env!("OUT_DIR"), "/defguard.client_types.rs")); + } + + pub mod enterprise { + pub mod posture { + pub mod v2 { + include!(concat!( + env!("OUT_DIR"), + "/defguard.enterprise.posture.v2.rs" + )); + } + } + } + + pub mod proxy { + pub mod v1 { + include!(concat!(env!("OUT_DIR"), "/defguard.proxy.v1.rs")); + } + } + } } #[derive(Clone, Default, Deserialize, Serialize)] struct CliConfig { private_key: Key, - device: proto::Device, - device_config: proto::DeviceConfig, - instance_info: proto::InstanceInfo, + device: Device, + device_config: DeviceConfig, + instance_info: InstanceInfo, // polling token used for further client-core communication token: Option, } @@ -283,11 +308,11 @@ async fn enroll(base_url: &Url, token: String) -> Result { url.set_path("/api/v1/enrollment/start"); let result = client .post(url) - .json(&proto::EnrollmentStartRequest { token }) + .json(&EnrollmentStartRequest { token }) .send() .await?; - let response: proto::EnrollmentStartResponse = if result.status() == StatusCode::OK { + let response: EnrollmentStartResponse = if result.status() == StatusCode::OK { let result = result.json().await?; debug!( "Enrollment start request has been successfully sent to Defguard Proxy. Received a \ @@ -314,7 +339,7 @@ async fn enroll(base_url: &Url, token: String) -> Result { url.set_path("/api/v1/enrollment/create_device"); let result = client .post(url) - .json(&proto::NewDevice { + .json(&NewDevice { // The name is ignored by the server as it's set by the user before the enrollment. name: String::new(), pubkey: pubkey.to_string(), @@ -323,7 +348,7 @@ async fn enroll(base_url: &Url, token: String) -> Result { .send() .await?; - let response: proto::DeviceConfigResponse = if result.status() == StatusCode::OK { + let response: DeviceConfigResponse = if result.status() == StatusCode::OK { let result = result.json().await?; debug!( "The device public key has been successfully sent to Defguard Proxy. The device should \ @@ -367,19 +392,15 @@ const INTERVAL_SECONDS: Duration = Duration::from_secs(30); const HTTP_REQ_TIMEOUT: Duration = Duration::from_secs(5); /// Fetch configuration from Defguard proxy. -async fn fetch_config( - client: &Client, - url: Url, - token: String, -) -> Result { +async fn fetch_config(client: &Client, url: Url, token: String) -> Result { let result = client .post(url.clone()) - .json(&proto::InstanceInfoRequest { token }) + .json(&InstanceInfoRequest { token }) .timeout(HTTP_REQ_TIMEOUT) .send() .await?; - let instance_response: proto::InstanceInfoResponse = if result.status() == StatusCode::OK { + let instance_response: InstanceInfoResponse = if result.status() == StatusCode::OK { result.json().await? } else if result.status() == StatusCode::PAYMENT_REQUIRED { return Err(CliError::EnterpriseDisabled); diff --git a/src-tauri/posture/Cargo.toml b/src-tauri/posture/Cargo.toml deleted file mode 100644 index 54639972..00000000 --- a/src-tauri/posture/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "posture" -authors.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -rust-version.workspace = true -version.workspace = true - -[dependencies] -sysinfo = {version = "0.39", default-features = false, features = ["apple-app-store", "system"]} - -[target.'cfg(windows)'.dependencies] -serde.workspace = true -wmi = {version = "0.18", default-features = false} diff --git a/src-tauri/posture/src/inspector/mod.rs b/src-tauri/posture/src/inspector/mod.rs deleted file mode 100644 index 75d31d0c..00000000 --- a/src-tauri/posture/src/inspector/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[cfg(target_os = "linux")] -pub(crate) mod linux; -#[cfg(target_os = "macos")] -pub(crate) mod macos; -#[cfg(windows)] -pub(crate) mod windows; diff --git a/src-tauri/proto b/src-tauri/proto index 5dfc8c8d..9b79da46 160000 --- a/src-tauri/proto +++ b/src-tauri/proto @@ -1 +1 @@ -Subproject commit 5dfc8c8d23ac0613108a2b7b921fd9a97613bb3a +Subproject commit 9b79da4667ec4ef66357269c4b1bf2d28c1f15a1 diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 1fc1c55f..0c93652d 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -36,7 +36,7 @@ use crate::{ global_log_watcher::{spawn_global_log_watcher_task, stop_global_log_watcher_task}, service_log_watcher::stop_log_watcher_task, }, - proto::DeviceConfigResponse, + proto::defguard::client_types::DeviceConfigResponse, tray::{configure_tray_icon, reload_tray_menu}, utils::{ construct_platform_header, disconnect_interface, get_location_interface_details, diff --git a/src-tauri/src/database/models/instance.rs b/src-tauri/src/database/models/instance.rs index 0227afce..9779e149 100644 --- a/src-tauri/src/database/models/instance.rs +++ b/src-tauri/src/database/models/instance.rs @@ -26,8 +26,8 @@ impl fmt::Display for Instance { } } -impl From for Instance { - fn from(instance_info: proto::InstanceInfo) -> Self { +impl From for Instance { + fn from(instance_info: proto::defguard::client_types::InstanceInfo) -> Self { let client_traffic_policy = ClientTrafficPolicy::from(&instance_info); Self { id: NoId, @@ -138,8 +138,8 @@ impl Instance { } // This compares proto::InstanceInfo, not to be confused with regular InstanceInfo defined below -impl PartialEq for Instance { - fn eq(&self, other: &proto::InstanceInfo) -> bool { +impl PartialEq for Instance { + fn eq(&self, other: &proto::defguard::client_types::InstanceInfo) -> bool { let other_policy = ClientTrafficPolicy::from(other); self.name == other.name && self.uuid == other.id @@ -223,8 +223,8 @@ pub enum ClientTrafficPolicy { } /// Retrieves `ClientTrafficPolicy` from `proto::InstanceInfo` while ensuring backwards compatibility -impl From<&proto::InstanceInfo> for ClientTrafficPolicy { - fn from(instance: &proto::InstanceInfo) -> Self { +impl From<&proto::defguard::client_types::InstanceInfo> for ClientTrafficPolicy { + fn from(instance: &proto::defguard::client_types::InstanceInfo) -> Self { match ( instance.client_traffic_policy, #[allow(deprecated)] diff --git a/src-tauri/src/database/models/location.rs b/src-tauri/src/database/models/location.rs index 7381bc29..7da68b61 100644 --- a/src-tauri/src/database/models/location.rs +++ b/src-tauri/src/database/models/location.rs @@ -17,7 +17,7 @@ use crate::{ }; use crate::{ error::Error, - proto::{ + proto::defguard::client_types::{ LocationMfaMode as ProtoLocationMfaMode, ServiceLocationMode as ProtoServiceLocationMode, }, }; diff --git a/src-tauri/posture/src/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs similarity index 100% rename from src-tauri/posture/src/inspector/linux.rs rename to src-tauri/src/enterprise/inspector/linux.rs diff --git a/src-tauri/posture/src/inspector/macos.rs b/src-tauri/src/enterprise/inspector/macos.rs similarity index 70% rename from src-tauri/posture/src/inspector/macos.rs rename to src-tauri/src/enterprise/inspector/macos.rs index 68b76ccb..62231350 100644 --- a/src-tauri/posture/src/inspector/macos.rs +++ b/src-tauri/src/enterprise/inspector/macos.rs @@ -1,6 +1,6 @@ use std::process::Command; -use crate::InspectionError; +use super::InspectionError; pub(crate) fn disk_encryption_status() -> Result { let output = Command::new("fdesetup") @@ -11,7 +11,3 @@ pub(crate) fn disk_encryption_status() -> Result { Ok(stdout.trim_end() == "true") } - -pub(crate) fn anti_virus_status() -> Result { - Err(InspectionError::NotApplicable) -} diff --git a/src-tauri/posture/src/lib.rs b/src-tauri/src/enterprise/inspector/mod.rs similarity index 86% rename from src-tauri/posture/src/lib.rs rename to src-tauri/src/enterprise/inspector/mod.rs index 6087219a..9b33edc9 100644 --- a/src-tauri/posture/src/lib.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -1,6 +1,11 @@ -mod inspector; +#[cfg(target_os = "linux")] +pub(crate) mod linux; +#[cfg(target_os = "macos")] +pub(crate) mod macos; #[cfg(test)] mod tests; +#[cfg(windows)] +pub(crate) mod windows; use std::{error::Error, fmt}; @@ -83,12 +88,12 @@ pub fn os_version() -> Result { pub fn disk_encryption_status() -> Result { #[cfg(target_os = "macos")] { - inspector::macos::disk_encryption_status() + macos::disk_encryption_status() } #[cfg(windows)] { - inspector::windows::disk_encryption_status() + windows::disk_encryption_status() } #[cfg(target_os = "linux")] @@ -99,18 +104,12 @@ pub fn disk_encryption_status() -> Result { } pub fn anti_virus_status() -> Result { - #[cfg(target_os = "macos")] - { - inspector::macos::anti_virus_status() - } - #[cfg(windows)] { - inspector::windows::anti_virus_status() + windows::anti_virus_status() } - #[cfg(target_os = "linux")] - // XXX + #[cfg(not(windows))] { Err(InspectionError::NotApplicable) } @@ -119,7 +118,7 @@ pub fn anti_virus_status() -> Result { pub fn part_of_domain() -> Result { #[cfg(windows)] { - inspector::windows::part_of_domain() + windows::part_of_domain() } #[cfg(not(windows))] diff --git a/src-tauri/posture/src/tests/linux.rs b/src-tauri/src/enterprise/inspector/tests/linux.rs similarity index 100% rename from src-tauri/posture/src/tests/linux.rs rename to src-tauri/src/enterprise/inspector/tests/linux.rs diff --git a/src-tauri/posture/src/tests/macos.rs b/src-tauri/src/enterprise/inspector/tests/macos.rs similarity index 79% rename from src-tauri/posture/src/tests/macos.rs rename to src-tauri/src/enterprise/inspector/tests/macos.rs index 8dcd1e4b..9f9bad54 100644 --- a/src-tauri/posture/src/tests/macos.rs +++ b/src-tauri/src/enterprise/inspector/tests/macos.rs @@ -1,4 +1,4 @@ -use crate::{disk_encryption_status, os_name, os_type, os_version, OsType}; +use super::super::{disk_encryption_status, os_name, os_type, os_version, OsType}; #[test] fn test_os_type() { diff --git a/src-tauri/posture/src/tests/mod.rs b/src-tauri/src/enterprise/inspector/tests/mod.rs similarity index 100% rename from src-tauri/posture/src/tests/mod.rs rename to src-tauri/src/enterprise/inspector/tests/mod.rs diff --git a/src-tauri/posture/src/tests/windows.rs b/src-tauri/src/enterprise/inspector/tests/windows.rs similarity index 100% rename from src-tauri/posture/src/tests/windows.rs rename to src-tauri/src/enterprise/inspector/tests/windows.rs diff --git a/src-tauri/posture/src/inspector/windows.rs b/src-tauri/src/enterprise/inspector/windows.rs similarity index 97% rename from src-tauri/posture/src/inspector/windows.rs rename to src-tauri/src/enterprise/inspector/windows.rs index 0681f65d..2e023b28 100644 --- a/src-tauri/posture/src/inspector/windows.rs +++ b/src-tauri/src/enterprise/inspector/windows.rs @@ -4,7 +4,7 @@ use serde::Deserialize; use wmi::{WMIConnection, WMIError}; -use crate::InspectionError; +use super::InspectionError; #[derive(Deserialize)] #[serde(rename = "Win32_EncryptableVolume")] @@ -96,6 +96,8 @@ pub(crate) fn anti_virus_status() -> Result { Ok(false) } +/// Check if this machine is part of an Active Directory domain. +/// /// Check manually in PowerShell: /// `Get-CimInstance -ClassName Win32_ComputerSystem` /// diff --git a/src-tauri/src/enterprise/mod.rs b/src-tauri/src/enterprise/mod.rs index 8e1f8e8a..6074c054 100644 --- a/src-tauri/src/enterprise/mod.rs +++ b/src-tauri/src/enterprise/mod.rs @@ -1,3 +1,4 @@ +pub mod inspector; pub mod models; pub mod periodic; pub mod provisioning; diff --git a/src-tauri/src/enterprise/periodic/config.rs b/src-tauri/src/enterprise/periodic/config.rs index 6153c822..7aca2494 100644 --- a/src-tauri/src/enterprise/periodic/config.rs +++ b/src-tauri/src/enterprise/periodic/config.rs @@ -21,7 +21,9 @@ use crate::{ }, error::Error, events::EventKey, - proto::{DeviceConfigResponse, InstanceInfoRequest, InstanceInfoResponse}, + proto::defguard::client_types::{ + DeviceConfigResponse, InstanceInfoRequest, InstanceInfoResponse, + }, utils::construct_platform_header, CLIENT_PLATFORM_HEADER, CLIENT_VERSION_HEADER, MIN_CORE_VERSION, MIN_PROXY_VERSION, PKG_VERSION, diff --git a/src-tauri/src/proto.rs b/src-tauri/src/proto.rs index ad041709..068bf5f9 100644 --- a/src-tauri/src/proto.rs +++ b/src-tauri/src/proto.rs @@ -3,9 +3,27 @@ use crate::database::models::{ Id, NoId, }; -tonic::include_proto!("defguard.proxy"); +pub(crate) mod defguard { + pub(crate) mod enterprise { + pub(crate) mod posture { + pub(crate) mod v2 { + tonic::include_proto!("defguard.enterprise.posture.v2"); + } + } + } + + pub(crate) mod proxy { + pub(crate) mod v1 { + tonic::include_proto!("defguard.proxy.v1"); + } + } + + pub mod client_types { + tonic::include_proto!("defguard.client_types"); + } +} -impl DeviceConfig { +impl defguard::client_types::DeviceConfig { #[must_use] pub(crate) fn into_location(self, instance_id: Id) -> Location { let location_mfa_mode = match self.location_mfa_mode { diff --git a/src-tauri/src/service/mod.rs b/src-tauri/src/service/mod.rs index 4d617432..9ba7bf30 100644 --- a/src-tauri/src/service/mod.rs +++ b/src-tauri/src/service/mod.rs @@ -2,7 +2,7 @@ pub mod client; pub mod config; pub mod proto { - tonic::include_proto!("client"); + tonic::include_proto!("defguard.client.v1"); } #[cfg(not(target_os = "macos"))] pub mod daemon; diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 7e0eb05c..3018e8ca 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -43,7 +43,7 @@ use crate::{ error::Error, events::EventKey, log_watcher::service_log_watcher::spawn_log_watcher_task, - proto::ClientPlatformInfo, + proto::defguard::client_types::ClientPlatformInfo, ConnectionType, }; #[cfg(not(target_os = "macos"))] From f679b44c1f9a11cc6e5aad491ea279af531d56b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Mon, 11 May 2026 11:52:27 +0200 Subject: [PATCH 03/11] migration: posture_check_required --- ...bb5148296157f00ef39610c18fc290da384bf.json | 20 ----------- ...ff42252aa0833f57c8ffa98e3471b9e663a1.json} | 10 ++++-- ...e22962668200b1ffb1fb7df967be5af0c50c.json} | 6 ++-- ...37ec18e3c0fd94b6ded74a60ac6edc57a5b3.json} | 10 ++++-- ...d8f373772e3c406f4482e6a4022a796cd46b.json} | 10 ++++-- ...df0afd4bd8488391475908272d9cf7c6dbd0.json} | 10 ++++-- src-tauri/Cargo.toml | 2 +- .../20260511093103_posture_check_required.sql | 1 + src-tauri/src/commands.rs | 4 +-- src-tauri/src/database/models/location.rs | 36 +++++++++++++------ src-tauri/src/proto.rs | 1 + 11 files changed, 66 insertions(+), 44 deletions(-) delete mode 100644 src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json rename src-tauri/.sqlx/{query-9137d3329ed718f211b5654af41b297c31706f5a5ad9ac400be116db7113a056.json => query-50543a38f8f09cd45b16bf8b93d2ff42252aa0833f57c8ffa98e3471b9e663a1.json} (84%) rename src-tauri/.sqlx/{query-ea39145f2cdc783bc78b32363cce32a87bd603debccaec23b160150766bdcd9f.json => query-7b9f3c02d868a7da19beed6aad5ee22962668200b1ffb1fb7df967be5af0c50c.json} (56%) rename src-tauri/.sqlx/{query-d8d908979a8573ee2c32828fa562d1bf171b4a6e224cc238680e2e856811c62e.json => query-858556d40a6fc015f2664045a00837ec18e3c0fd94b6ded74a60ac6edc57a5b3.json} (77%) rename src-tauri/.sqlx/{query-76c5c9b75df39afca9cd07530ab0569d3d6f9d8924458c8b357dd400966f4175.json => query-865203f8f64866f1895aede956dfd8f373772e3c406f4482e6a4022a796cd46b.json} (86%) rename src-tauri/.sqlx/{query-85f8edf373d3bf1d405a8fed804d9d04839e69a6c2c5cb8ad5c2f8e19547a2f6.json => query-ec008998cc09e79017a3edd82550df0afd4bd8488391475908272d9cf7c6dbd0.json} (86%) create mode 100644 src-tauri/migrations/20260511093103_posture_check_required.sql diff --git a/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json b/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json deleted file mode 100644 index acfde086..00000000 --- a/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT name FROM location WHERE id = $1", - "describe": { - "columns": [ - { - "name": "name", - "ordinal": 0, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf" -} diff --git a/src-tauri/.sqlx/query-9137d3329ed718f211b5654af41b297c31706f5a5ad9ac400be116db7113a056.json b/src-tauri/.sqlx/query-50543a38f8f09cd45b16bf8b93d2ff42252aa0833f57c8ffa98e3471b9e663a1.json similarity index 84% rename from src-tauri/.sqlx/query-9137d3329ed718f211b5654af41b297c31706f5a5ad9ac400be116db7113a056.json rename to src-tauri/.sqlx/query-50543a38f8f09cd45b16bf8b93d2ff42252aa0833f57c8ffa98e3471b9e663a1.json index 012a54b3..7692367f 100644 --- a/src-tauri/.sqlx/query-9137d3329ed718f211b5654af41b297c31706f5a5ad9ac400be116db7113a056.json +++ b/src-tauri/.sqlx/query-50543a38f8f09cd45b16bf8b93d2ff42252aa0833f57c8ffa98e3471b9e663a1.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM location WHERE instance_id = $1 AND service_location_mode <= $2 ORDER BY name ASC", + "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\",\n posture_check_required FROM location WHERE instance_id = $1 AND service_location_mode <= $2 ORDER BY name ASC", "describe": { "columns": [ { @@ -67,6 +67,11 @@ "name": "service_location_mode: ServiceLocationMode", "ordinal": 12, "type_info": "Integer" + }, + { + "name": "posture_check_required", + "ordinal": 13, + "type_info": "Bool" } ], "parameters": { @@ -85,8 +90,9 @@ false, false, false, + false, false ] }, - "hash": "9137d3329ed718f211b5654af41b297c31706f5a5ad9ac400be116db7113a056" + "hash": "50543a38f8f09cd45b16bf8b93d2ff42252aa0833f57c8ffa98e3471b9e663a1" } diff --git a/src-tauri/.sqlx/query-ea39145f2cdc783bc78b32363cce32a87bd603debccaec23b160150766bdcd9f.json b/src-tauri/.sqlx/query-7b9f3c02d868a7da19beed6aad5ee22962668200b1ffb1fb7df967be5af0c50c.json similarity index 56% rename from src-tauri/.sqlx/query-ea39145f2cdc783bc78b32363cce32a87bd603debccaec23b160150766bdcd9f.json rename to src-tauri/.sqlx/query-7b9f3c02d868a7da19beed6aad5ee22962668200b1ffb1fb7df967be5af0c50c.json index a05f49a0..7eb7d1e7 100644 --- a/src-tauri/.sqlx/query-ea39145f2cdc783bc78b32363cce32a87bd603debccaec23b160150766bdcd9f.json +++ b/src-tauri/.sqlx/query-7b9f3c02d868a7da19beed6aad5ee22962668200b1ffb1fb7df967be5af0c50c.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "INSERT INTO location (instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode, service_location_mode) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING id \"id!\"", + "query": "INSERT INTO location (instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode, service_location_mode, posture_check_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING id \"id!\"", "describe": { "columns": [ { @@ -10,11 +10,11 @@ } ], "parameters": { - "Right": 12 + "Right": 13 }, "nullable": [ true ] }, - "hash": "ea39145f2cdc783bc78b32363cce32a87bd603debccaec23b160150766bdcd9f" + "hash": "7b9f3c02d868a7da19beed6aad5ee22962668200b1ffb1fb7df967be5af0c50c" } diff --git a/src-tauri/.sqlx/query-d8d908979a8573ee2c32828fa562d1bf171b4a6e224cc238680e2e856811c62e.json b/src-tauri/.sqlx/query-858556d40a6fc015f2664045a00837ec18e3c0fd94b6ded74a60ac6edc57a5b3.json similarity index 77% rename from src-tauri/.sqlx/query-d8d908979a8573ee2c32828fa562d1bf171b4a6e224cc238680e2e856811c62e.json rename to src-tauri/.sqlx/query-858556d40a6fc015f2664045a00837ec18e3c0fd94b6ded74a60ac6edc57a5b3.json index e023a3a7..c6135a03 100644 --- a/src-tauri/.sqlx/query-d8d908979a8573ee2c32828fa562d1bf171b4a6e224cc238680e2e856811c62e.json +++ b/src-tauri/.sqlx/query-858556d40a6fc015f2664045a00837ec18e3c0fd94b6ded74a60ac6edc57a5b3.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "SELECT id, instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id,route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM location WHERE service_location_mode <= $1 ORDER BY name ASC;", + "query": "SELECT id, instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\", posture_check_required FROM location WHERE service_location_mode <= $1 ORDER BY name ASC;", "describe": { "columns": [ { @@ -67,6 +67,11 @@ "name": "service_location_mode: ServiceLocationMode", "ordinal": 12, "type_info": "Integer" + }, + { + "name": "posture_check_required", + "ordinal": 13, + "type_info": "Bool" } ], "parameters": { @@ -85,8 +90,9 @@ false, false, false, + false, false ] }, - "hash": "d8d908979a8573ee2c32828fa562d1bf171b4a6e224cc238680e2e856811c62e" + "hash": "858556d40a6fc015f2664045a00837ec18e3c0fd94b6ded74a60ac6edc57a5b3" } diff --git a/src-tauri/.sqlx/query-76c5c9b75df39afca9cd07530ab0569d3d6f9d8924458c8b357dd400966f4175.json b/src-tauri/.sqlx/query-865203f8f64866f1895aede956dfd8f373772e3c406f4482e6a4022a796cd46b.json similarity index 86% rename from src-tauri/.sqlx/query-76c5c9b75df39afca9cd07530ab0569d3d6f9d8924458c8b357dd400966f4175.json rename to src-tauri/.sqlx/query-865203f8f64866f1895aede956dfd8f373772e3c406f4482e6a4022a796cd46b.json index 9c6f65ed..ddf2ceb9 100644 --- a/src-tauri/.sqlx/query-76c5c9b75df39afca9cd07530ab0569d3d6f9d8924458c8b357dd400966f4175.json +++ b/src-tauri/.sqlx/query-865203f8f64866f1895aede956dfd8f373772e3c406f4482e6a4022a796cd46b.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM location WHERE id = $1", + "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\",\n posture_check_required FROM location WHERE id = $1", "describe": { "columns": [ { @@ -67,6 +67,11 @@ "name": "service_location_mode: ServiceLocationMode", "ordinal": 12, "type_info": "Integer" + }, + { + "name": "posture_check_required", + "ordinal": 13, + "type_info": "Bool" } ], "parameters": { @@ -85,8 +90,9 @@ false, false, false, + false, false ] }, - "hash": "76c5c9b75df39afca9cd07530ab0569d3d6f9d8924458c8b357dd400966f4175" + "hash": "865203f8f64866f1895aede956dfd8f373772e3c406f4482e6a4022a796cd46b" } diff --git a/src-tauri/.sqlx/query-85f8edf373d3bf1d405a8fed804d9d04839e69a6c2c5cb8ad5c2f8e19547a2f6.json b/src-tauri/.sqlx/query-ec008998cc09e79017a3edd82550df0afd4bd8488391475908272d9cf7c6dbd0.json similarity index 86% rename from src-tauri/.sqlx/query-85f8edf373d3bf1d405a8fed804d9d04839e69a6c2c5cb8ad5c2f8e19547a2f6.json rename to src-tauri/.sqlx/query-ec008998cc09e79017a3edd82550df0afd4bd8488391475908272d9cf7c6dbd0.json index 1615e9b4..dd6d4011 100644 --- a/src-tauri/.sqlx/query-85f8edf373d3bf1d405a8fed804d9d04839e69a6c2c5cb8ad5c2f8e19547a2f6.json +++ b/src-tauri/.sqlx/query-ec008998cc09e79017a3edd82550df0afd4bd8488391475908272d9cf7c6dbd0.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM location WHERE pubkey = $1;", + "query": "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\",\n posture_check_required FROM location WHERE pubkey = $1;", "describe": { "columns": [ { @@ -67,6 +67,11 @@ "name": "service_location_mode: ServiceLocationMode", "ordinal": 12, "type_info": "Integer" + }, + { + "name": "posture_check_required", + "ordinal": 13, + "type_info": "Bool" } ], "parameters": { @@ -85,8 +90,9 @@ false, false, false, + false, false ] }, - "hash": "85f8edf373d3bf1d405a8fed804d9d04839e69a6c2c5cb8ad5c2f8e19547a2f6" + "hash": "ec008998cc09e79017a3edd82550df0afd4bd8488391475908272d9cf7c6dbd0" } diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 66da9a35..d343604f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -86,7 +86,7 @@ sqlx = { version = "0.8", features = [ ] } struct-patch = "0.11" strum = { version = "0.28", features = ["derive"] } -sysinfo = {version = "0.39", default-features = false, features = ["apple-app-store", "system"]} +sysinfo = { version = "0.39", default-features = false, features = ["apple-app-store", "system"] } tauri = { version = "2", features = [ "native-tls-vendored", "image-png", diff --git a/src-tauri/migrations/20260511093103_posture_check_required.sql b/src-tauri/migrations/20260511093103_posture_check_required.sql new file mode 100644 index 00000000..c9743138 --- /dev/null +++ b/src-tauri/migrations/20260511093103_posture_check_required.sql @@ -0,0 +1 @@ +ALTER TABLE location ADD COLUMN posture_check_required BOOLEAN NOT NULL DEFAULT false; diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 0c93652d..65e1f49d 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -242,7 +242,7 @@ pub async fn save_device_config( let instance_info = response .instance .expect("Missing instance info in device config response"); - let mut instance: Instance = instance_info.into(); + let mut instance = Instance::from(instance_info); if response.token.is_some() { debug!( "The newly saved device config has a polling token, automatic configuration polling \ @@ -250,7 +250,7 @@ pub async fn save_device_config( ); } else { warn!( - "Missing polling token for instance {}, core and/or proxy services may need an update, \ + "Missing polling token for instance {}, Core and/or Edge services may need an update, \ configuration polling won't work", instance.name, ); diff --git a/src-tauri/src/database/models/location.rs b/src-tauri/src/database/models/location.rs index 7da68b61..7ed2669f 100644 --- a/src-tauri/src/database/models/location.rs +++ b/src-tauri/src/database/models/location.rs @@ -80,6 +80,8 @@ pub struct Location { pub keepalive_interval: i64, pub location_mfa_mode: LocationMfaMode, pub service_location_mode: ServiceLocationMode, + #[serde(default)] + pub posture_check_required: bool, } impl fmt::Display for Location { @@ -107,14 +109,16 @@ impl Location { let max_service_location_mode = Self::get_service_location_mode_filter(include_service_locations); query_as!( - Self, - "SELECT id, instance_id, name, address, pubkey, endpoint, allowed_ips, dns, network_id,\ - route_all_traffic, keepalive_interval, \ - location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" \ + Self, + "SELECT id, instance_id, name, address, pubkey, endpoint, allowed_ips, dns, \ + network_id, route_all_traffic, keepalive_interval, \ + location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ + service_location_mode \"service_location_mode: ServiceLocationMode\", \ + posture_check_required \ FROM location WHERE service_location_mode <= $1 \ ORDER BY name ASC;", max_service_location_mode - ) + ) .fetch_all(executor) .await } @@ -159,7 +163,9 @@ impl Location { Self, "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, \ network_id, route_all_traffic, keepalive_interval, \ - location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" \ + location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ + service_location_mode \"service_location_mode: ServiceLocationMode\", + posture_check_required \ FROM location WHERE id = $1", location_id ) @@ -180,7 +186,10 @@ impl Location { query_as!( Self, "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, \ - network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" \ + network_id, route_all_traffic, keepalive_interval, \ + location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ + service_location_mode \"service_location_mode: ServiceLocationMode\", + posture_check_required \ FROM location WHERE instance_id = $1 AND service_location_mode <= $2 \ ORDER BY name ASC", instance_id, @@ -200,7 +209,10 @@ impl Location { query_as!( Self, "SELECT id \"id: _\", instance_id, name, address, pubkey, endpoint, allowed_ips, dns, \ - network_id, route_all_traffic, keepalive_interval, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" \ + network_id, route_all_traffic, keepalive_interval, \ + location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ + service_location_mode \"service_location_mode: ServiceLocationMode\", + posture_check_required \ FROM location WHERE pubkey = $1;", pubkey ) @@ -364,8 +376,9 @@ impl Location { // Insert a new record when there is no ID let id = query_scalar!( "INSERT INTO location (instance_id, name, address, pubkey, endpoint, allowed_ips, \ - dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode, service_location_mode) \ - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) \ + dns, network_id, route_all_traffic, keepalive_interval, location_mfa_mode, \ + service_location_mode, posture_check_required) \ + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) \ RETURNING id \"id!\"", self.instance_id, self.name, @@ -379,6 +392,7 @@ impl Location { self.keepalive_interval, self.location_mfa_mode, self.service_location_mode, + self.posture_check_required, ) .fetch_one(executor) .await?; @@ -397,6 +411,7 @@ impl Location { keepalive_interval: self.keepalive_interval, location_mfa_mode: self.location_mfa_mode, service_location_mode: self.service_location_mode, + posture_check_required: self.posture_check_required, }) } } @@ -424,6 +439,7 @@ impl From> for Location { keepalive_interval: location.keepalive_interval, location_mfa_mode: location.location_mfa_mode, service_location_mode: location.service_location_mode, + posture_check_required: location.posture_check_required, } } } diff --git a/src-tauri/src/proto.rs b/src-tauri/src/proto.rs index 068bf5f9..bbc7341d 100644 --- a/src-tauri/src/proto.rs +++ b/src-tauri/src/proto.rs @@ -59,6 +59,7 @@ impl defguard::client_types::DeviceConfig { keepalive_interval: self.keepalive_interval.into(), location_mfa_mode, service_location_mode, + posture_check_required: self.posture_check_required.unwrap_or_default(), } } } From 4a6980e241b0dc76320f71e09534dd1d65f9465e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Mon, 11 May 2026 13:58:35 +0200 Subject: [PATCH 04/11] impl DevicePostureData --- biome.json | 14 +- package.json | 6 +- pnpm-lock.yaml | 148 +++++++++--------- ...bb5148296157f00ef39610c18fc290da384bf.json | 20 +++ src-tauri/proto | 2 +- src-tauri/src/commands.rs | 25 ++- src-tauri/src/database/models/location.rs | 8 +- src-tauri/src/enterprise/inspector/linux.rs | 10 +- src-tauri/src/enterprise/inspector/macos.rs | 6 +- src-tauri/src/enterprise/inspector/mod.rs | 107 ++++++++++--- .../src/enterprise/inspector/tests/linux.rs | 2 +- .../src/enterprise/inspector/tests/macos.rs | 1 + .../src/enterprise/inspector/tests/windows.rs | 5 +- src-tauri/src/enterprise/inspector/windows.rs | 33 ++-- src-tauri/src/tray.rs | 10 +- .../client/components/MfaModalProvider.tsx | 17 +- src/pages/client/types.ts | 1 + 17 files changed, 248 insertions(+), 167 deletions(-) create mode 100644 src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json diff --git a/biome.json b/biome.json index 92a029b6..4bc6b7c6 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.4.13/schema.json", + "$schema": "https://biomejs.dev/schemas/2.4.15/schema.json", "vcs": { "enabled": false, "clientKind": "git", @@ -27,9 +27,7 @@ "bracketSpacing": true, "expand": "auto", "useEditorconfig": true, - "includes": [ - "./src/**" - ] + "includes": ["./src/**"] }, "linter": { "enabled": true, @@ -70,9 +68,7 @@ "noArrayIndexKey": "off" } }, - "includes": [ - "src/**" - ] + "includes": ["src/**"] }, "javascript": { "formatter": { @@ -94,9 +90,7 @@ }, "overrides": [ { - "includes": [ - "**/*.js" - ] + "includes": ["**/*.js"] } ], "assist": { diff --git a/package.json b/package.json index ff2796d7..62033df3 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "zustand": "^5.0.13" }, "devDependencies": { - "@biomejs/biome": "^2.4.14", + "@biomejs/biome": "^2.4.15", "@hookform/devtools": "^4.4.0", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.100.9", @@ -120,7 +120,7 @@ "@tauri-apps/cli": "^2.11.1", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^24.12.2", + "@types/node": "^24.12.3", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.2.0", @@ -133,7 +133,7 @@ "typedoc": "^0.28.19", "typesafe-i18n": "^5.27.1", "typescript": "^5.9.3", - "vite": "^7.3.2" + "vite": "^7.3.3" }, "volta": { "node": "20.5.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83620c22..4ff73c6a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,11 +184,11 @@ importers: version: 3.25.76 zustand: specifier: ^5.0.13 - version: 5.0.13(@types/react@19.2.14)(immer@11.1.7)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)) + version: 5.0.13(@types/react@19.2.14)(immer@11.1.8)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)) devDependencies: '@biomejs/biome': - specifier: ^2.4.14 - version: 2.4.14 + specifier: ^2.4.15 + version: 2.4.15 '@hookform/devtools': specifier: ^4.4.0 version: 4.4.0(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -211,8 +211,8 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/node': - specifier: ^24.12.2 - version: 24.12.2 + specifier: ^24.12.3 + version: 24.12.3 '@types/react': specifier: ^19.2.14 version: 19.2.14 @@ -221,10 +221,10 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^5.2.0 - version: 5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4)) + version: 5.2.0(vite@7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4)) '@vitejs/plugin-react-swc': specifier: ^4.3.0 - version: 4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4)) + version: 4.3.0(vite@7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4)) autoprefixer: specifier: ^10.5.0 version: 10.5.0(postcss@8.5.14) @@ -250,8 +250,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 vite: - specifier: ^7.3.2 - version: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) + specifier: ^7.3.3 + version: 7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4) packages: @@ -342,59 +342,59 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.4.14': - resolution: {integrity: sha512-TmAvxOEgrpLypzVGJ8FulIZnlyA9TxrO1hyqYrCz9r+bwma9xXxuLA5IuYnj55XQneFx460KjRbx6SWGLkg3bQ==} + '@biomejs/biome@2.4.15': + resolution: {integrity: sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.4.14': - resolution: {integrity: sha512-XvgoE9XOawUOQPdmvs4J7wPhi/DLwSCGks3AlPJDmh34O0awRTqCED1HRcRDdpf1Zrp4us4MGOOdIxNpbqNF5Q==} + '@biomejs/cli-darwin-arm64@2.4.15': + resolution: {integrity: sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.4.14': - resolution: {integrity: sha512-jE7hKBCFhOx3uUh+ZkWBfOHxAcILPfhFplNkuID/eZeSTLHzfZzoZxW8fbqY9xXRnPi7jGNAf1iPVR+0yWsM/Q==} + '@biomejs/cli-darwin-x64@2.4.15': + resolution: {integrity: sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.4.14': - resolution: {integrity: sha512-/z+6gqAqqUQTHazwStxSXKHg9b8UvqBmDFRp+c4wYbq2KXhELQDon9EoC9RpmQ8JWkqQx/lIUy/cs+MhzDZp6A==} + '@biomejs/cli-linux-arm64-musl@2.4.15': + resolution: {integrity: sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [musl] - '@biomejs/cli-linux-arm64@2.4.14': - resolution: {integrity: sha512-2TELhZnW5RSLL063l9rc5xLpA0ZIw0Ccwy/0q384rvNAgFw3yI76bd59547yxowdQr5MNPET/xDLrLuvgSeeWQ==} + '@biomejs/cli-linux-arm64@2.4.15': + resolution: {integrity: sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [glibc] - '@biomejs/cli-linux-x64-musl@2.4.14': - resolution: {integrity: sha512-R6BWgJdQOwW9ulJatuTVrQkjnODjqHZkKNOqb1sz++3Noe5LYd0i3PchnOBUCYAPHoPWHhjJqbdZlHEu0hpjdA==} + '@biomejs/cli-linux-x64-musl@2.4.15': + resolution: {integrity: sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [musl] - '@biomejs/cli-linux-x64@2.4.14': - resolution: {integrity: sha512-zHrlQZDBDUz4OLAraYpWKcnLS6HOewBFWYOzY91d1ZjdqZwibOyb6BEu6WuWLugyo0P3riCmsbV9UqV1cSXwQg==} + '@biomejs/cli-linux-x64@2.4.15': + resolution: {integrity: sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [glibc] - '@biomejs/cli-win32-arm64@2.4.14': - resolution: {integrity: sha512-M3EH5hqOI/F/FUA2u4xcLoUgmxd218mvuj/6JL7Hv2toQvr2/AdOvKSpGkoRuWFCtQPVa+ZqkEV3Q5xBA9+XSA==} + '@biomejs/cli-win32-arm64@2.4.15': + resolution: {integrity: sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.4.14': - resolution: {integrity: sha512-WL0EG5qE+EAKomGXbf2g6VnSKJhTL3tXC0QRzWRwA5VpjxNYa6H4P7ZWfymbGE4IhZZQi1KXQ2R0YjwInmz2fA==} + '@biomejs/cli-win32-x64@2.4.15': + resolution: {integrity: sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -1355,8 +1355,8 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@24.12.2': - resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + '@types/node@24.12.3': + resolution: {integrity: sha512-8oljBDGun9cIsZRJR6fkihn0TSXJI0UDOOhncYaERq6M0JMDoPLxyscwruJcb4GKS6dvK/d8xebYBg27h/duaQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -1453,8 +1453,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.27: - resolution: {integrity: sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==} + baseline-browser-mapping@2.10.29: + resolution: {integrity: sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -1467,8 +1467,8 @@ packages: brace-expansion@2.1.0: resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} - brace-expansion@5.0.5: - resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} browserslist@4.28.2: @@ -1749,8 +1749,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.352: - resolution: {integrity: sha512-9wHk8x6dyuimoe18EdiDPWKExNdxYqo4fn4FwOVVper6RxT3cmpBwBkWWfSOCYJjQdIco/nPhJhNLmn4Ufg1Yg==} + electron-to-chromium@1.5.353: + resolution: {integrity: sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1986,8 +1986,8 @@ packages: immer@10.2.0: resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} - immer@11.1.7: - resolution: {integrity: sha512-LFVFtAROHcDy1er5UI6nodRFnZ2SgdCXhfNSI+DpObO8N7Pur/muBGsjzH5wpnFHCYhYVQxZskCkV4koQ//3/Q==} + immer@11.1.8: + resolution: {integrity: sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==} immutable@5.1.5: resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==} @@ -2946,8 +2946,8 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite@7.3.2: - resolution: {integrity: sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==} + vite@7.3.3: + resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3177,39 +3177,39 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.4.14': + '@biomejs/biome@2.4.15': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.4.14 - '@biomejs/cli-darwin-x64': 2.4.14 - '@biomejs/cli-linux-arm64': 2.4.14 - '@biomejs/cli-linux-arm64-musl': 2.4.14 - '@biomejs/cli-linux-x64': 2.4.14 - '@biomejs/cli-linux-x64-musl': 2.4.14 - '@biomejs/cli-win32-arm64': 2.4.14 - '@biomejs/cli-win32-x64': 2.4.14 - - '@biomejs/cli-darwin-arm64@2.4.14': + '@biomejs/cli-darwin-arm64': 2.4.15 + '@biomejs/cli-darwin-x64': 2.4.15 + '@biomejs/cli-linux-arm64': 2.4.15 + '@biomejs/cli-linux-arm64-musl': 2.4.15 + '@biomejs/cli-linux-x64': 2.4.15 + '@biomejs/cli-linux-x64-musl': 2.4.15 + '@biomejs/cli-win32-arm64': 2.4.15 + '@biomejs/cli-win32-x64': 2.4.15 + + '@biomejs/cli-darwin-arm64@2.4.15': optional: true - '@biomejs/cli-darwin-x64@2.4.14': + '@biomejs/cli-darwin-x64@2.4.15': optional: true - '@biomejs/cli-linux-arm64-musl@2.4.14': + '@biomejs/cli-linux-arm64-musl@2.4.15': optional: true - '@biomejs/cli-linux-arm64@2.4.14': + '@biomejs/cli-linux-arm64@2.4.15': optional: true - '@biomejs/cli-linux-x64-musl@2.4.14': + '@biomejs/cli-linux-x64-musl@2.4.15': optional: true - '@biomejs/cli-linux-x64@2.4.14': + '@biomejs/cli-linux-x64@2.4.15': optional: true - '@biomejs/cli-win32-arm64@2.4.14': + '@biomejs/cli-win32-arm64@2.4.15': optional: true - '@biomejs/cli-win32-x64@2.4.14': + '@biomejs/cli-win32-x64@2.4.15': optional: true '@emotion/babel-plugin@11.13.5': @@ -3524,7 +3524,7 @@ snapshots: dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 - immer: 11.1.7 + immer: 11.1.8 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) reselect: 5.1.1 @@ -4018,7 +4018,7 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@24.12.2': + '@types/node@24.12.3': dependencies: undici-types: 7.16.0 @@ -4047,15 +4047,15 @@ snapshots: '@use-gesture/core': 10.3.1 react: 19.2.6 - '@vitejs/plugin-react-swc@4.3.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4))': + '@vitejs/plugin-react-swc@4.3.0(vite@7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 '@swc/core': 1.15.33 - vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) + vite: 7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@5.2.0(vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4))': + '@vitejs/plugin-react@5.2.0(vite@7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -4063,7 +4063,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4) + vite: 7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4) transitivePeerDependencies: - supports-color @@ -4121,7 +4121,7 @@ snapshots: balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.27: {} + baseline-browser-mapping@2.10.29: {} boolbase@1.0.0: {} @@ -4134,15 +4134,15 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.5: + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.27 + baseline-browser-mapping: 2.10.29 caniuse-lite: 1.0.30001792 - electron-to-chromium: 1.5.352 + electron-to-chromium: 1.5.353 node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) @@ -4409,7 +4409,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.352: {} + electron-to-chromium@1.5.353: {} emoji-regex@8.0.0: {} @@ -4721,7 +4721,7 @@ snapshots: immer@10.2.0: {} - immer@11.1.7: {} + immer@11.1.8: {} immutable@5.1.5: {} @@ -5182,7 +5182,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.5 + brace-expansion: 5.0.6 minimatch@3.1.5: dependencies: @@ -5924,7 +5924,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@7.3.2(@types/node@24.12.2)(sass@1.92.1)(yaml@2.8.4): + vite@7.3.3(@types/node@24.12.3)(sass@1.92.1)(yaml@2.8.4): dependencies: esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) @@ -5933,7 +5933,7 @@ snapshots: rollup: 4.60.3 tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.3 fsevents: 2.3.3 sass: 1.92.1 yaml: 2.8.4 @@ -6013,10 +6013,10 @@ snapshots: zod@3.25.76: {} - zustand@5.0.13(@types/react@19.2.14)(immer@11.1.7)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)): + zustand@5.0.13(@types/react@19.2.14)(immer@11.1.8)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)): optionalDependencies: '@types/react': 19.2.14 - immer: 11.1.7 + immer: 11.1.8 react: 19.2.6 use-sync-external-store: 1.6.0(react@19.2.6) diff --git a/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json b/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json new file mode 100644 index 00000000..acfde086 --- /dev/null +++ b/src-tauri/.sqlx/query-2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT name FROM location WHERE id = $1", + "describe": { + "columns": [ + { + "name": "name", + "ordinal": 0, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "2e752bd9e60b5ddd0c9eeeabb6cbb5148296157f00ef39610c18fc290da384bf" +} diff --git a/src-tauri/proto b/src-tauri/proto index 9b79da46..84a2bf71 160000 --- a/src-tauri/proto +++ b/src-tauri/proto @@ -1 +1 @@ -Subproject commit 9b79da4667ec4ef66357269c4b1bf2d28c1f15a1 +Subproject commit 84a2bf71b1435d956cae2f7933ab9b7e880292b6 diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 65e1f49d..7b4e00b8 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -539,22 +539,21 @@ pub(crate) async fn locations_changed( instance: &Instance, device_config: &DeviceConfigResponse, ) -> Result { - let db_locations: HashSet> = - Location::find_by_instance_id(transaction.as_mut(), instance.id, true) - .await? - .into_iter() - .map(|location| { - let mut new_location = Location::::from(location); - // Ignore `route_all_traffic` flag as Defguard core does not have it. - new_location.route_all_traffic = false; - new_location - }) - .collect(); - let core_locations: HashSet = device_config + let db_locations = Location::find_by_instance_id(transaction.as_mut(), instance.id, true) + .await? + .into_iter() + .map(|location| { + let mut new_location = Location::::from(location); + // Ignore `route_all_traffic` flag as Defguard core does not have it. + new_location.route_all_traffic = false; + new_location + }) + .collect::>(); + let core_locations = device_config .configs .iter() .map(|config| config.clone().into_location(instance.id)) - .collect(); + .collect::>(); Ok(db_locations != core_locations) } diff --git a/src-tauri/src/database/models/location.rs b/src-tauri/src/database/models/location.rs index 7ed2669f..54829cc6 100644 --- a/src-tauri/src/database/models/location.rs +++ b/src-tauri/src/database/models/location.rs @@ -131,7 +131,8 @@ impl Location { query!( "UPDATE location SET instance_id = $1, name = $2, address = $3, pubkey = $4, \ endpoint = $5, allowed_ips = $6, dns = $7, network_id = $8, route_all_traffic = $9, \ - keepalive_interval = $10, location_mfa_mode = $11, service_location_mode = $12 WHERE id = $13", + keepalive_interval = $10, location_mfa_mode = $11, service_location_mode = $12 \ + WHERE id = $13", self.instance_id, self.name, self.address, @@ -357,8 +358,9 @@ impl Location { Ok(interface_config) } - /// Returns a filter value that can be used in SQL queries like `service_location_mode <= ?` when querying locations - /// to exclude (<= 1) or include service locations (all service locations modes). + /// Returns a filter value that can be used in SQL queries like `service_location_mode <= ?` + /// when querying locations to exclude (<= 1) or include service locations (all service + /// locations modes). fn get_service_location_mode_filter(include_service_locations: bool) -> i32 { if include_service_locations { i32::MAX diff --git a/src-tauri/src/enterprise/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs index dd6ccc25..9abab145 100644 --- a/src-tauri/src/enterprise/inspector/linux.rs +++ b/src-tauri/src/enterprise/inspector/linux.rs @@ -1,7 +1,7 @@ use std::process::Command; /// Determine if any block device has "crypto_LUKS" type. -fn check_luks() -> Result { +fn check_luks() -> Result { let output = Command::new("lsblk") .args(["-o", "NAME,FSTYPE,TYPE"]) .output() @@ -15,11 +15,11 @@ fn check_luks() -> Result { } // https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 -pub fn disk_encryption_status() -> Result { +pub fn disk_encryption_status() -> Result { // TODO: zfs encryption - Err(InspectionError::NotApplicable) + Err(UnavailableReason::NotApplicable) } -pub(crate) fn anti_virus_status() -> Result { - Err(InspectionError::NotApplicable) +pub(crate) fn anti_virus_status() -> Result { + Err(UnavailableReason::NotApplicable) } diff --git a/src-tauri/src/enterprise/inspector/macos.rs b/src-tauri/src/enterprise/inspector/macos.rs index 62231350..baf0fc97 100644 --- a/src-tauri/src/enterprise/inspector/macos.rs +++ b/src-tauri/src/enterprise/inspector/macos.rs @@ -1,12 +1,12 @@ use std::process::Command; -use super::InspectionError; +use super::UnavailableReason; -pub(crate) fn disk_encryption_status() -> Result { +pub(crate) fn disk_encryption_status() -> Result { let output = Command::new("fdesetup") .arg("isactive") .output() - .map_err(|_| InspectionError::DetectionFailed)?; + .map_err(|_| UnavailableReason::DetectionFailed)?; let stdout = String::from_utf8_lossy(&output.stdout); Ok(stdout.trim_end() == "true") diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index 9b33edc9..6e765c05 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -11,33 +11,46 @@ use std::{error::Error, fmt}; use sysinfo::System; -#[derive(Debug)] -pub enum InspectionError { - DetectionFailed, - NotApplicable, - PermissionDenied, -} - -impl fmt::Display for InspectionError { +use crate::{ + proto::defguard::enterprise::posture::v2::{ + bool_check, string_check, BoolCheck, DevicePostureData, StringCheck, UnavailableReason, + }, + VERSION, +}; + +impl fmt::Display for UnavailableReason { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + Self::Unspecified => f.write_str("nspecified"), Self::DetectionFailed => f.write_str("detection failed"), Self::NotApplicable => f.write_str("not applicable on this platform"), - Self::PermissionDenied => f.write_str("permission denied"), + Self::InsufficientPermissions => f.write_str("insufficient permissions"), } } } -impl Error for InspectionError {} +impl Error for UnavailableReason {} pub enum OsType { - MacOS, FreeBSD, Linux, + MacOS, NetBSD, Windows, } +impl fmt::Display for OsType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::FreeBSD => f.write_str("FreeBSD"), + Self::Linux => f.write_str("Linux"), + Self::MacOS => f.write_str("macOS"), + Self::NetBSD => f.write_str("NetBSD"), + Self::Windows => f.write_str("Windows"), + } + } +} + impl OsType { /// Returns OS type for the running machine. /// Note: Unsupported machines won't compile. @@ -69,23 +82,27 @@ pub fn os_type() -> OsType { OsType::this_machine() } -pub fn os_name() -> Result { - System::name().ok_or_else(|| InspectionError::DetectionFailed) +pub fn os_name() -> Result { + System::name().ok_or_else(|| UnavailableReason::DetectionFailed) } -pub fn os_version() -> Result { +pub fn os_version() -> Result { + System::os_version().ok_or_else(|| UnavailableReason::DetectionFailed) +} + +pub fn linux_kernel_version() -> Result { #[cfg(target_os = "linux")] { - System::kernel_version().ok_or_else(|| InspectionError::DetectionFailed) + System::kernel_version().ok_or_else(|| UnavailableReason::DetectionFailed) } #[cfg(not(target_os = "linux"))] { - System::os_version().ok_or_else(|| InspectionError::DetectionFailed) + Err(UnavailableReason::NotApplicable) } } -pub fn disk_encryption_status() -> Result { +pub fn disk_encryption_status() -> Result { #[cfg(target_os = "macos")] { macos::disk_encryption_status() @@ -99,11 +116,11 @@ pub fn disk_encryption_status() -> Result { #[cfg(target_os = "linux")] // XXX { - Err(InspectionError::NotApplicable) + Err(UnavailableReason::NotApplicable) } } -pub fn anti_virus_status() -> Result { +pub fn anti_virus_status() -> Result { #[cfg(windows)] { windows::anti_virus_status() @@ -111,11 +128,11 @@ pub fn anti_virus_status() -> Result { #[cfg(not(windows))] { - Err(InspectionError::NotApplicable) + Err(UnavailableReason::NotApplicable) } } -pub fn part_of_domain() -> Result { +pub fn part_of_domain() -> Result { #[cfg(windows)] { windows::part_of_domain() @@ -123,6 +140,52 @@ pub fn part_of_domain() -> Result { #[cfg(not(windows))] { - Err(InspectionError::NotApplicable) + Err(UnavailableReason::NotApplicable) + } +} + +fn device_integrity() -> Result { + Err(UnavailableReason::NotApplicable) +} + +impl From> for BoolCheck { + fn from(value: Result) -> Self { + Self { + result: Some(match value { + Ok(inner) => bool_check::Result::Value(inner), + Err(err) => bool_check::Result::Unavailable(err as i32), + }), + } + } +} + +impl From> for StringCheck { + fn from(value: Result) -> Self { + Self { + result: Some(match value { + Ok(inner) => string_check::Result::Value(inner), + Err(err) => string_check::Result::Unavailable(err as i32), + }), + } + } +} + +impl DevicePostureData { + /// Do system inspection and return results. + #[must_use] + pub fn new() -> Self { + Self { + defguard_client_version: VERSION.to_owned(), + os_type: os_type().to_string(), + os_name: Some(StringCheck::from(os_name())), + os_version: Some(StringCheck::from(os_version())), + disk_encryption: Some(BoolCheck::from(disk_encryption_status())), + antivirus_present: Some(BoolCheck::from(anti_virus_status())), + windows_ad_domain_joined: Some(BoolCheck::from(part_of_domain())), + // Not implemented + windows_security_update_current: None, + linux_kernel_version: Some(StringCheck::from(linux_kernel_version())), + device_integrity: Some(BoolCheck::from(device_integrity())), + } } } diff --git a/src-tauri/src/enterprise/inspector/tests/linux.rs b/src-tauri/src/enterprise/inspector/tests/linux.rs index 3290cf77..2cce594b 100644 --- a/src-tauri/src/enterprise/inspector/tests/linux.rs +++ b/src-tauri/src/enterprise/inspector/tests/linux.rs @@ -1,4 +1,4 @@ -use crate::{os_name, os_type, OsType}; +use super::super::{os_name, os_type, OsType}; #[test] fn test_os_type() { diff --git a/src-tauri/src/enterprise/inspector/tests/macos.rs b/src-tauri/src/enterprise/inspector/tests/macos.rs index 9f9bad54..70671db7 100644 --- a/src-tauri/src/enterprise/inspector/tests/macos.rs +++ b/src-tauri/src/enterprise/inspector/tests/macos.rs @@ -16,6 +16,7 @@ fn test_os_version() { } #[test] +#[ignore = "development machine only"] fn test_disk_encryption() { assert!(disk_encryption_status().unwrap()); } diff --git a/src-tauri/src/enterprise/inspector/tests/windows.rs b/src-tauri/src/enterprise/inspector/tests/windows.rs index 8921a7a6..9ac01ba6 100644 --- a/src-tauri/src/enterprise/inspector/tests/windows.rs +++ b/src-tauri/src/enterprise/inspector/tests/windows.rs @@ -1,4 +1,4 @@ -use crate::{ +use super::super::{ anti_virus_status, disk_encryption_status, os_name, os_type, os_version, part_of_domain, OsType, }; @@ -18,16 +18,19 @@ fn test_os_version() { } #[test] +#[ignore = "development machine only"] fn test_disk_encryption() { assert!(!disk_encryption_status().unwrap()); } #[test] +#[ignore = "development machine only"] fn test_anti_virus() { assert!(anti_virus_status().unwrap()); } #[test] +#[ignore = "development machine only"] fn test_part_of_domain() { assert!(!part_of_domain().unwrap()); } diff --git a/src-tauri/src/enterprise/inspector/windows.rs b/src-tauri/src/enterprise/inspector/windows.rs index 2e023b28..f4ad7a91 100644 --- a/src-tauri/src/enterprise/inspector/windows.rs +++ b/src-tauri/src/enterprise/inspector/windows.rs @@ -4,7 +4,7 @@ use serde::Deserialize; use wmi::{WMIConnection, WMIError}; -use super::InspectionError; +use super::UnavailableReason; #[derive(Deserialize)] #[serde(rename = "Win32_EncryptableVolume")] @@ -34,30 +34,30 @@ struct Win32ComputerSystem { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftVolumeEncryption" -query "SELECT * FROM Win32_EncryptableVolume"` -pub(crate) fn disk_encryption_status() -> Result { +pub(crate) fn disk_encryption_status() -> Result { let conn = WMIConnection::with_namespace_path("root\\CIMV2\\Security\\MicrosoftVolumeEncryption") .map_err(|err| { if let WMIError::HResultError { .. } = err { - InspectionError::PermissionDenied + UnavailableReason::InsufficientPermissions } else { - InspectionError::DetectionFailed + UnavailableReason::DetectionFailed } })?; let volumes: Vec = conn .raw_query("SELECT ProtectionStatus FROM Win32_EncryptableVolume WHERE DriveLetter='C:'") - .map_err(|_| InspectionError::DetectionFailed)?; + .map_err(|_| UnavailableReason::DetectionFailed)?; match volumes.first() { Some(vol) => { return match vol.protection_status { 0 => Ok(false), 1 => Ok(true), - _ => Err(InspectionError::DetectionFailed), + _ => Err(UnavailableReason::DetectionFailed), }; } - None => Err(InspectionError::DetectionFailed), + None => Err(UnavailableReason::DetectionFailed), } } @@ -68,17 +68,18 @@ pub(crate) fn disk_encryption_status() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\SecurityCenter2" -query "SELECT * FROM AntiVirusProduct"` -pub(crate) fn anti_virus_status() -> Result { +pub(crate) fn anti_virus_status() -> Result { let conn = WMIConnection::with_namespace_path("root\\SecurityCenter2").map_err(|err| { if let WMIError::HResultError { .. } = err { - InspectionError::PermissionDenied + UnavailableReason::InsufficientPermissions } else { - InspectionError::DetectionFailed + UnavailableReason::DetectionFailed } })?; - let products: Vec = - conn.query().map_err(|_| InspectionError::DetectionFailed)?; + let products: Vec = conn + .query() + .map_err(|_| UnavailableReason::DetectionFailed)?; if products.is_empty() { return Ok(false); @@ -103,18 +104,18 @@ pub(crate) fn anti_virus_status() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -query "SELECT * FROM Win32_ComputerSystem"` -pub(crate) fn part_of_domain() -> Result { +pub(crate) fn part_of_domain() -> Result { let conn = WMIConnection::new().map_err(|err| { if let WMIError::HResultError { .. } = err { - InspectionError::PermissionDenied + UnavailableReason::InsufficientPermissions } else { - InspectionError::DetectionFailed + UnavailableReason::DetectionFailed } })?; let system = conn .get::() - .map_err(|_| InspectionError::DetectionFailed)?; + .map_err(|_| UnavailableReason::DetectionFailed)?; Ok(system.part_of_domain) } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 94ff99c7..21d388e9 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -271,19 +271,13 @@ async fn handle_location_tray_menu(id: String, app: &AppHandle) { info!("Connect location with ID {id}"); // Check if MFA is enabled. If so, trigger modal on frontend. if location.mfa_enabled() { - info!( - "MFA enabled for location with ID {:?}, trigger MFA modal", - location.id - ); + info!("MFA enabled for location with ID {id}, trigger MFA modal"); show_main_window(app); let _ = app.emit(EventKey::MfaTrigger.into(), &location); } else if let Err(err) = connect(location_id, ConnectionType::Location, None, app.clone()).await { - info!( - "Unable to connect location with ID {}, error: {err:?}", - location.id - ); + info!("Unable to connect location with ID {id}, error: {err:?}",); } } } diff --git a/src/pages/client/components/MfaModalProvider.tsx b/src/pages/client/components/MfaModalProvider.tsx index 680100c5..50447b69 100644 --- a/src/pages/client/components/MfaModalProvider.tsx +++ b/src/pages/client/components/MfaModalProvider.tsx @@ -3,7 +3,7 @@ import { type PropsWithChildren, useEffect } from 'react'; import { isPresent } from '../../../shared/defguard-ui/utils/isPresent'; import { MFAModal } from '../pages/ClientInstancePage/components/LocationsList/modals/MFAModal/MFAModal'; import { useMFAModal } from '../pages/ClientInstancePage/components/LocationsList/modals/MFAModal/useMFAModal'; -import type { CommonWireguardFields } from '../types'; +import { type CommonWireguardFields, TauriEventKey } from '../types'; type Props = PropsWithChildren; @@ -13,17 +13,20 @@ type Payload = { export const MfaModalProvider = ({ children }: Props) => { const openMFAModal = useMFAModal((state) => state.open); - // listen for rust backend requesting MFA + // listen for Rust backend requesting MFA useEffect(() => { let unlisten: UnlistenFn; (async () => { - unlisten = await listen('mfa-trigger', ({ payload: { location } }) => { - if (isPresent(location)) { - openMFAModal(location); - } - }); + unlisten = await listen( + TauriEventKey.MFA_TRIGGER, + ({ payload: { location } }) => { + if (isPresent(location)) { + openMFAModal(location); + } + }, + ); })(); return () => { diff --git a/src/pages/client/types.ts b/src/pages/client/types.ts index 3434187b..8c0b1e66 100644 --- a/src/pages/client/types.ts +++ b/src/pages/client/types.ts @@ -75,6 +75,7 @@ export type CommonWireguardFields = { pubkey: string; instance_id: number; network_id: number; + // TODO: device posture data, if available }; export type SelectedInstance = { From da3b5b9228a9087ad1ff3a9a7b90af60d861a6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 11:10:10 +0200 Subject: [PATCH 05/11] More detectors --- src-tauri/Cargo.lock | 4 +- src-tauri/src/enterprise/inspector/macos.rs | 12 ++ src-tauri/src/enterprise/inspector/mod.rs | 26 +++- .../src/enterprise/inspector/tests/windows.rs | 9 +- src-tauri/src/enterprise/inspector/windows.rs | 128 ++++++++++++------ .../src/log_watcher/global_log_watcher.rs | 2 +- src-tauri/src/periodic/purge_stats.rs | 3 +- src-tauri/src/periodic/version.rs | 2 +- src-tauri/src/tray.rs | 2 +- 9 files changed, 137 insertions(+), 51 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2c6fba91..000f4803 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4158,9 +4158,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.4" +version = "5.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3bab717c29a857abf75fcef718d441ec7cb2725f937343c734740a985d37fd" +checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" dependencies = [ "dunce", "is-wsl", diff --git a/src-tauri/src/enterprise/inspector/macos.rs b/src-tauri/src/enterprise/inspector/macos.rs index baf0fc97..d16166fe 100644 --- a/src-tauri/src/enterprise/inspector/macos.rs +++ b/src-tauri/src/enterprise/inspector/macos.rs @@ -2,6 +2,7 @@ use std::process::Command; use super::UnavailableReason; +/// Check if FileVault has been enabled. pub(crate) fn disk_encryption_status() -> Result { let output = Command::new("fdesetup") .arg("isactive") @@ -11,3 +12,14 @@ pub(crate) fn disk_encryption_status() -> Result { Ok(stdout.trim_end() == "true") } + +/// Check if System Integrity Protection has been enabled. +pub(crate) fn system_integrity_status() -> Result { + let output = Command::new("csrutil") + .arg("status") + .output() + .map_err(|_| UnavailableReason::DetectionFailed)?; + let stdout = String::from_utf8_lossy(&output.stdout); + + Ok(stdout.trim_end() == "System Integrity Protection status: enabled.") +} diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index 6e765c05..2556345b 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -54,6 +54,7 @@ impl fmt::Display for OsType { impl OsType { /// Returns OS type for the running machine. /// Note: Unsupported machines won't compile. + #[must_use] pub fn this_machine() -> Self { #[cfg(target_os = "macos")] { @@ -78,16 +79,17 @@ impl OsType { } } +#[must_use] pub fn os_type() -> OsType { OsType::this_machine() } pub fn os_name() -> Result { - System::name().ok_or_else(|| UnavailableReason::DetectionFailed) + System::name().ok_or(UnavailableReason::DetectionFailed) } pub fn os_version() -> Result { - System::os_version().ok_or_else(|| UnavailableReason::DetectionFailed) + System::os_version().ok_or(UnavailableReason::DetectionFailed) } pub fn linux_kernel_version() -> Result { @@ -145,9 +147,27 @@ pub fn part_of_domain() -> Result { } fn device_integrity() -> Result { + #[cfg(target_os = "macos")] + { + macos::system_integrity_status() + } + + #[cfg(not(target_os = "macos"))] Err(UnavailableReason::NotApplicable) } +fn security_update_status() -> Result { + #[cfg(windows)] + { + windows::security_update_status() + } + + #[cfg(not(windows))] + { + Err(UnavailableReason::NotApplicable) + } +} + impl From> for BoolCheck { fn from(value: Result) -> Self { Self { @@ -183,7 +203,7 @@ impl DevicePostureData { antivirus_present: Some(BoolCheck::from(anti_virus_status())), windows_ad_domain_joined: Some(BoolCheck::from(part_of_domain())), // Not implemented - windows_security_update_current: None, + windows_security_update_current: Some(BoolCheck::from(security_update_status())), linux_kernel_version: Some(StringCheck::from(linux_kernel_version())), device_integrity: Some(BoolCheck::from(device_integrity())), } diff --git a/src-tauri/src/enterprise/inspector/tests/windows.rs b/src-tauri/src/enterprise/inspector/tests/windows.rs index 9ac01ba6..a9a11805 100644 --- a/src-tauri/src/enterprise/inspector/tests/windows.rs +++ b/src-tauri/src/enterprise/inspector/tests/windows.rs @@ -1,5 +1,6 @@ use super::super::{ - anti_virus_status, disk_encryption_status, os_name, os_type, os_version, part_of_domain, OsType, + anti_virus_status, disk_encryption_status, os_name, os_type, os_version, part_of_domain, + security_update_status, OsType, }; #[test] @@ -34,3 +35,9 @@ fn test_anti_virus() { fn test_part_of_domain() { assert!(!part_of_domain().unwrap()); } + +#[test] +#[ignore = "development machine only"] +fn test_security_update_status() { + assert!(security_update_status().unwrap()); +} diff --git a/src-tauri/src/enterprise/inspector/windows.rs b/src-tauri/src/enterprise/inspector/windows.rs index f4ad7a91..23689075 100644 --- a/src-tauri/src/enterprise/inspector/windows.rs +++ b/src-tauri/src/enterprise/inspector/windows.rs @@ -1,11 +1,14 @@ // TODO: use `async_raw_query` use serde::Deserialize; +use time::{Date, OffsetDateTime}; -use wmi::{WMIConnection, WMIError}; +use wmi::{AuthLevel, WMIConnection, WMIError}; use super::UnavailableReason; +const MAX_QUICKFIX_DAYS: i64 = 60; + #[derive(Deserialize)] #[serde(rename = "Win32_EncryptableVolume")] #[serde(rename_all = "PascalCase")] @@ -30,24 +33,67 @@ struct Win32ComputerSystem { part_of_domain: bool, } +#[derive(Deserialize)] +#[serde(rename = "Win32_OperatingSystem")] +#[serde(rename_all = "PascalCase")] +struct Win32OperatingSystem { + system_drive: String, +} + +// Custom format for `installed_on`. +time::serde::format_description!( + wmidate, + Date, + "[month padding:none]/[day padding:none]/[year]" +); + +#[derive(Deserialize)] +#[serde(rename = "Win32_QuickFixEngineering")] +#[serde(rename_all = "PascalCase")] +struct Win32QuickFixEngineering { + //hot_fix_id: String, + #[serde(with = "wmidate::option", default)] + installed_on: Option, + //description: Option, // "Update" or "Security Update" +} + +/// Convert `WMIError` to `UnavailableReason`. +impl From for UnavailableReason { + fn from(err: WMIError) -> Self { + if let WMIError::HResultError { .. } = err { + UnavailableReason::InsufficientPermissions + } else { + UnavailableReason::DetectionFailed + } + } +} + +/// Determine system drive letter. +fn system_drive_letter() -> Result { + let conn = WMIConnection::new()?; + let mut results: Vec = conn.query()?; + match results.pop() { + Some(result) => Ok(result.system_drive), + None => Err(UnavailableReason::DetectionFailed), + } +} + /// This requires Administrator access, and only detects BitLocker for drive C:. /// /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftVolumeEncryption" -query "SELECT * FROM Win32_EncryptableVolume"` pub(crate) fn disk_encryption_status() -> Result { + let drive_letter = system_drive_letter()?; + let conn = - WMIConnection::with_namespace_path("root\\CIMV2\\Security\\MicrosoftVolumeEncryption") - .map_err(|err| { - if let WMIError::HResultError { .. } = err { - UnavailableReason::InsufficientPermissions - } else { - UnavailableReason::DetectionFailed - } - })?; - - let volumes: Vec = conn - .raw_query("SELECT ProtectionStatus FROM Win32_EncryptableVolume WHERE DriveLetter='C:'") - .map_err(|_| UnavailableReason::DetectionFailed)?; + WMIConnection::with_namespace_path("root\\CIMV2\\Security\\MicrosoftVolumeEncryption")?; + conn.set_proxy_blanket(AuthLevel::PktPrivacy)?; + + let volumes: Vec = conn.raw_query(format!( + "SELECT ProtectionStatus FROM Win32_EncryptableVolume WHERE DriveLetter='{drive_letter}'" + ))?; + + // XXX: query all drives and .filter()? match volumes.first() { Some(vol) => { @@ -69,22 +115,8 @@ pub(crate) fn disk_encryption_status() -> Result { /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\SecurityCenter2" -query "SELECT * FROM AntiVirusProduct"` pub(crate) fn anti_virus_status() -> Result { - let conn = WMIConnection::with_namespace_path("root\\SecurityCenter2").map_err(|err| { - if let WMIError::HResultError { .. } = err { - UnavailableReason::InsufficientPermissions - } else { - UnavailableReason::DetectionFailed - } - })?; - - let products: Vec = conn - .query() - .map_err(|_| UnavailableReason::DetectionFailed)?; - - if products.is_empty() { - return Ok(false); - } - + let conn = WMIConnection::with_namespace_path("root\\SecurityCenter2")?; + let products: Vec = conn.query()?; for product in products { let enabled = (product.product_state & 0x0001_0000) != 0; let realtime = (product.product_state & 0x0002_0000) != 0; @@ -105,17 +137,33 @@ pub(crate) fn anti_virus_status() -> Result { /// Equivalent to PowerShell command: /// `Get-WmiObject -query "SELECT * FROM Win32_ComputerSystem"` pub(crate) fn part_of_domain() -> Result { - let conn = WMIConnection::new().map_err(|err| { - if let WMIError::HResultError { .. } = err { - UnavailableReason::InsufficientPermissions - } else { - UnavailableReason::DetectionFailed - } - })?; + let conn = WMIConnection::new()?; + let system = conn.get::()?; + Ok(system.part_of_domain) +} - let system = conn - .get::() - .map_err(|_| UnavailableReason::DetectionFailed)?; +/// Find the latest security patch. +/// +/// Check manually in PowerShell: +/// `Get-CimInstance -ClassName Win32_QuickFixEngineering` +/// +/// Equivalent to PowerShell command: +/// `Get-WmiObject -query "SELECT * FROM Win32_QuickFixEngineering"` +pub(crate) fn security_update_status() -> Result { + let conn = WMIConnection::new()?; + let fixes: Vec = conn.query().unwrap(); + + // Days from today + let today = OffsetDateTime::now_utc().date(); + let mut max_days = i64::MAX; + for fix in fixes { + if let Some(installed_on) = fix.installed_on { + let days = (today - installed_on).whole_days(); + if days < max_days { + max_days = days; + } + } + } - Ok(system.part_of_domain) + Ok(max_days <= MAX_QUICKFIX_DAYS) } diff --git a/src-tauri/src/log_watcher/global_log_watcher.rs b/src-tauri/src/log_watcher/global_log_watcher.rs index 74ed2b82..86a92d71 100644 --- a/src-tauri/src/log_watcher/global_log_watcher.rs +++ b/src-tauri/src/log_watcher/global_log_watcher.rs @@ -637,7 +637,7 @@ pub async fn spawn_global_log_watcher_task( let app_state = handle.state::(); // Show logs only from the last hour - let from = Some(Utc::now() - Duration::from_secs(60 * 60)); + let from = Some(Utc::now() - Duration::from_hours(1)); let event_topic = "log-update-global".to_string(); diff --git a/src-tauri/src/periodic/purge_stats.rs b/src-tauri/src/periodic/purge_stats.rs index 81fafd06..c8ca2494 100644 --- a/src-tauri/src/periodic/purge_stats.rs +++ b/src-tauri/src/periodic/purge_stats.rs @@ -7,8 +7,7 @@ use crate::database::{ DB_POOL, }; -// 12 hours -const PURGE_INTERVAL: Duration = Duration::from_secs(12 * 60 * 60); +const PURGE_INTERVAL: Duration = Duration::from_hours(12); /// Periodically purges location and tunnel stats. /// diff --git a/src-tauri/src/periodic/version.rs b/src-tauri/src/periodic/version.rs index 9b8b9c10..b58c5c13 100644 --- a/src-tauri/src/periodic/version.rs +++ b/src-tauri/src/periodic/version.rs @@ -5,7 +5,7 @@ use tokio::time::interval; use crate::{appstate::AppState, commands::get_latest_app_version, events::EventKey}; -const INTERVAL_IN_SECONDS: Duration = Duration::from_secs(12 * 60 * 60); // 12 hours +const INTERVAL_IN_SECONDS: Duration = Duration::from_hours(12); pub async fn poll_version(app_handle: AppHandle) { debug!("Starting the latest application version polling loop."); diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 21d388e9..db6fcca1 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -277,7 +277,7 @@ async fn handle_location_tray_menu(id: String, app: &AppHandle) { } else if let Err(err) = connect(location_id, ConnectionType::Location, None, app.clone()).await { - info!("Unable to connect location with ID {id}, error: {err:?}",); + info!("Unable to connect location with ID {id}, error: {err:?}"); } } } From ca258bdf41f34ac5c225fa1bbdc7cc0a3eaad606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 11:43:28 +0200 Subject: [PATCH 06/11] comments --- src-tauri/src/enterprise/inspector/mod.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index 2556345b..35ff006d 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -31,6 +31,7 @@ impl fmt::Display for UnavailableReason { impl Error for UnavailableReason {} +/// Operating system type. pub enum OsType { FreeBSD, Linux, @@ -52,7 +53,7 @@ impl fmt::Display for OsType { } impl OsType { - /// Returns OS type for the running machine. + /// Returns the OS type of the current machine. /// Note: Unsupported machines won't compile. #[must_use] pub fn this_machine() -> Self { @@ -79,19 +80,23 @@ impl OsType { } } +/// Returns the operating system type. #[must_use] pub fn os_type() -> OsType { OsType::this_machine() } +/// Returns the operating system name. pub fn os_name() -> Result { System::name().ok_or(UnavailableReason::DetectionFailed) } +/// Returns the operating system version. pub fn os_version() -> Result { System::os_version().ok_or(UnavailableReason::DetectionFailed) } +/// Returns the Linux kernel version. pub fn linux_kernel_version() -> Result { #[cfg(target_os = "linux")] { @@ -104,6 +109,7 @@ pub fn linux_kernel_version() -> Result { } } +/// Returns the disk encryption status, preferably for the system volume. pub fn disk_encryption_status() -> Result { #[cfg(target_os = "macos")] { @@ -122,6 +128,7 @@ pub fn disk_encryption_status() -> Result { } } +/// Returns the antivirus status. pub fn anti_virus_status() -> Result { #[cfg(windows)] { @@ -134,6 +141,7 @@ pub fn anti_virus_status() -> Result { } } +/// Checks whether the computer is part of a domain. pub fn part_of_domain() -> Result { #[cfg(windows)] { @@ -146,6 +154,7 @@ pub fn part_of_domain() -> Result { } } +/// Returns the device integrity status. fn device_integrity() -> Result { #[cfg(target_os = "macos")] { @@ -156,6 +165,7 @@ fn device_integrity() -> Result { Err(UnavailableReason::NotApplicable) } +/// Returns the security update status. fn security_update_status() -> Result { #[cfg(windows)] { @@ -168,6 +178,7 @@ fn security_update_status() -> Result { } } +/// Convert `Result` to `BoolCheck`. impl From> for BoolCheck { fn from(value: Result) -> Self { Self { @@ -179,6 +190,7 @@ impl From> for BoolCheck { } } +/// Convert `Result` to `StringCheck`. impl From> for StringCheck { fn from(value: Result) -> Self { Self { @@ -191,7 +203,7 @@ impl From> for StringCheck { } impl DevicePostureData { - /// Do system inspection and return results. + /// Performs system inspection and returns the results. #[must_use] pub fn new() -> Self { Self { @@ -202,7 +214,6 @@ impl DevicePostureData { disk_encryption: Some(BoolCheck::from(disk_encryption_status())), antivirus_present: Some(BoolCheck::from(anti_virus_status())), windows_ad_domain_joined: Some(BoolCheck::from(part_of_domain())), - // Not implemented windows_security_update_current: Some(BoolCheck::from(security_update_status())), linux_kernel_version: Some(StringCheck::from(linux_kernel_version())), device_integrity: Some(BoolCheck::from(device_integrity())), From 9957ad06cac947d4ebd964e454dfb0c54126a7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 12:55:26 +0200 Subject: [PATCH 07/11] Linux: disk_encryption_status --- src-tauri/src/enterprise/inspector/linux.rs | 57 +++++++++++++++++-- src-tauri/src/enterprise/inspector/mod.rs | 3 +- .../src/enterprise/inspector/tests/linux.rs | 8 ++- .../src/enterprise/inspector/tests/macos.rs | 10 +++- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src-tauri/src/enterprise/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs index 9abab145..6c1b4016 100644 --- a/src-tauri/src/enterprise/inspector/linux.rs +++ b/src-tauri/src/enterprise/inspector/linux.rs @@ -1,14 +1,61 @@ use std::process::Command; +use serde::Deserialize; + +use super::UnavailableReason; + +#[derive(Deserialize)] +struct LsblkDevice { + fstype: Option, + #[serde(rename = "type")] + device_type: Option, + children: Option>, +} + +impl LsblkDevice { + // Check if device is encrypted. + #[must_use] + fn is_crypto(&self) -> bool { + if let Some(fstype) = &self.fstype { + fstype == "crypto_LUKS" + } else if let Some(device_type) = &self.device_type { + device_type == "crypt" + } else { + false + } + } +} + +#[derive(Deserialize)] +struct LsblkOutput { + blockdevices: Vec, +} + /// Determine if any block device has "crypto_LUKS" type. fn check_luks() -> Result { let output = Command::new("lsblk") - .args(["-o", "NAME,FSTYPE,TYPE"]) + .args(["-Jo", "NAME,FSTYPE,TYPE"]) .output() - .map_err(|_| ())?; - + .map_err(|_| UnavailableReason::DetectionFailed)?; if !output.status.success() { - return Err(()); + return Err(UnavailableReason::DetectionFailed); + } + + let output: LsblkOutput = + serde_json::from_slice(&output.stdout).map_err(|_| UnavailableReason::DetectionFailed)?; + + // Check for LUKS. + for device in output.blockdevices { + if device.is_crypto() { + return Ok(true); + } + if let Some(children) = &device.children { + for child in children { + if child.is_crypto() { + return Ok(true); + } + } + } } Ok(false) @@ -17,7 +64,7 @@ fn check_luks() -> Result { // https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 pub fn disk_encryption_status() -> Result { // TODO: zfs encryption - Err(UnavailableReason::NotApplicable) + check_luks() } pub(crate) fn anti_virus_status() -> Result { diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index 35ff006d..b5564c8d 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -122,9 +122,8 @@ pub fn disk_encryption_status() -> Result { } #[cfg(target_os = "linux")] - // XXX { - Err(UnavailableReason::NotApplicable) + linux::disk_encryption_status() } } diff --git a/src-tauri/src/enterprise/inspector/tests/linux.rs b/src-tauri/src/enterprise/inspector/tests/linux.rs index 2cce594b..c437993a 100644 --- a/src-tauri/src/enterprise/inspector/tests/linux.rs +++ b/src-tauri/src/enterprise/inspector/tests/linux.rs @@ -1,4 +1,4 @@ -use super::super::{os_name, os_type, OsType}; +use super::super::{disk_encryption_status, os_name, os_type, os_version, OsType}; #[test] fn test_os_type() { @@ -14,3 +14,9 @@ fn test_os_name() { fn test_os_version() { assert!(os_version().is_ok()); } + +#[test] +#[ignore = "development machine only"] +fn test_disk_encryption() { + assert!(!disk_encryption_status().unwrap()); +} diff --git a/src-tauri/src/enterprise/inspector/tests/macos.rs b/src-tauri/src/enterprise/inspector/tests/macos.rs index 70671db7..c2f628a5 100644 --- a/src-tauri/src/enterprise/inspector/tests/macos.rs +++ b/src-tauri/src/enterprise/inspector/tests/macos.rs @@ -1,4 +1,6 @@ -use super::super::{disk_encryption_status, os_name, os_type, os_version, OsType}; +use super::super::{ + device_integrity, disk_encryption_status, os_name, os_type, os_version, OsType, +}; #[test] fn test_os_type() { @@ -20,3 +22,9 @@ fn test_os_version() { fn test_disk_encryption() { assert!(disk_encryption_status().unwrap()); } + +#[test] +#[ignore = "development machine only"] +fn test_device_integrity() { + assert!(device_integrity().unwrap()); +} From d3775d8169dbd1c92db5029e41ac79c9eaa9e1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 13:00:57 +0200 Subject: [PATCH 08/11] Cleanup --- src-tauri/src/enterprise/inspector/linux.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/enterprise/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs index 6c1b4016..782c6615 100644 --- a/src-tauri/src/enterprise/inspector/linux.rs +++ b/src-tauri/src/enterprise/inspector/linux.rs @@ -62,11 +62,8 @@ fn check_luks() -> Result { } // https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 -pub fn disk_encryption_status() -> Result { +// FIXME: This will check all available disks, so if any is encrypted, it will succeed. +pub(crate) fn disk_encryption_status() -> Result { // TODO: zfs encryption check_luks() } - -pub(crate) fn anti_virus_status() -> Result { - Err(UnavailableReason::NotApplicable) -} From 3d01652da163f17a1c624f07f92c5b477a8d8121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 13:08:04 +0200 Subject: [PATCH 09/11] Visibility change --- src-tauri/src/enterprise/inspector/linux.rs | 2 +- src-tauri/src/enterprise/inspector/macos.rs | 4 ++-- src-tauri/src/enterprise/inspector/mod.rs | 14 +++++++------- src-tauri/src/enterprise/inspector/windows.rs | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src-tauri/src/enterprise/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs index 782c6615..a99fb3fe 100644 --- a/src-tauri/src/enterprise/inspector/linux.rs +++ b/src-tauri/src/enterprise/inspector/linux.rs @@ -63,7 +63,7 @@ fn check_luks() -> Result { // https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 // FIXME: This will check all available disks, so if any is encrypted, it will succeed. -pub(crate) fn disk_encryption_status() -> Result { +pub(super) fn disk_encryption_status() -> Result { // TODO: zfs encryption check_luks() } diff --git a/src-tauri/src/enterprise/inspector/macos.rs b/src-tauri/src/enterprise/inspector/macos.rs index d16166fe..779aaaf2 100644 --- a/src-tauri/src/enterprise/inspector/macos.rs +++ b/src-tauri/src/enterprise/inspector/macos.rs @@ -3,7 +3,7 @@ use std::process::Command; use super::UnavailableReason; /// Check if FileVault has been enabled. -pub(crate) fn disk_encryption_status() -> Result { +pub(super) fn disk_encryption_status() -> Result { let output = Command::new("fdesetup") .arg("isactive") .output() @@ -14,7 +14,7 @@ pub(crate) fn disk_encryption_status() -> Result { } /// Check if System Integrity Protection has been enabled. -pub(crate) fn system_integrity_status() -> Result { +pub(super) fn system_integrity_status() -> Result { let output = Command::new("csrutil") .arg("status") .output() diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index b5564c8d..710a502a 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -82,22 +82,22 @@ impl OsType { /// Returns the operating system type. #[must_use] -pub fn os_type() -> OsType { +fn os_type() -> OsType { OsType::this_machine() } /// Returns the operating system name. -pub fn os_name() -> Result { +fn os_name() -> Result { System::name().ok_or(UnavailableReason::DetectionFailed) } /// Returns the operating system version. -pub fn os_version() -> Result { +fn os_version() -> Result { System::os_version().ok_or(UnavailableReason::DetectionFailed) } /// Returns the Linux kernel version. -pub fn linux_kernel_version() -> Result { +fn linux_kernel_version() -> Result { #[cfg(target_os = "linux")] { System::kernel_version().ok_or_else(|| UnavailableReason::DetectionFailed) @@ -110,7 +110,7 @@ pub fn linux_kernel_version() -> Result { } /// Returns the disk encryption status, preferably for the system volume. -pub fn disk_encryption_status() -> Result { +fn disk_encryption_status() -> Result { #[cfg(target_os = "macos")] { macos::disk_encryption_status() @@ -128,7 +128,7 @@ pub fn disk_encryption_status() -> Result { } /// Returns the antivirus status. -pub fn anti_virus_status() -> Result { +fn anti_virus_status() -> Result { #[cfg(windows)] { windows::anti_virus_status() @@ -141,7 +141,7 @@ pub fn anti_virus_status() -> Result { } /// Checks whether the computer is part of a domain. -pub fn part_of_domain() -> Result { +fn part_of_domain() -> Result { #[cfg(windows)] { windows::part_of_domain() diff --git a/src-tauri/src/enterprise/inspector/windows.rs b/src-tauri/src/enterprise/inspector/windows.rs index 23689075..ff86a671 100644 --- a/src-tauri/src/enterprise/inspector/windows.rs +++ b/src-tauri/src/enterprise/inspector/windows.rs @@ -82,7 +82,7 @@ fn system_drive_letter() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftVolumeEncryption" -query "SELECT * FROM Win32_EncryptableVolume"` -pub(crate) fn disk_encryption_status() -> Result { +pub(super) fn disk_encryption_status() -> Result { let drive_letter = system_drive_letter()?; let conn = @@ -114,7 +114,7 @@ pub(crate) fn disk_encryption_status() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -Namespace "root\SecurityCenter2" -query "SELECT * FROM AntiVirusProduct"` -pub(crate) fn anti_virus_status() -> Result { +pub(super) fn anti_virus_status() -> Result { let conn = WMIConnection::with_namespace_path("root\\SecurityCenter2")?; let products: Vec = conn.query()?; for product in products { @@ -136,7 +136,7 @@ pub(crate) fn anti_virus_status() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -query "SELECT * FROM Win32_ComputerSystem"` -pub(crate) fn part_of_domain() -> Result { +pub(super) fn part_of_domain() -> Result { let conn = WMIConnection::new()?; let system = conn.get::()?; Ok(system.part_of_domain) @@ -149,7 +149,7 @@ pub(crate) fn part_of_domain() -> Result { /// /// Equivalent to PowerShell command: /// `Get-WmiObject -query "SELECT * FROM Win32_QuickFixEngineering"` -pub(crate) fn security_update_status() -> Result { +pub(super) fn security_update_status() -> Result { let conn = WMIConnection::new()?; let fixes: Vec = conn.query().unwrap(); From 80b9c3a8f43119bd8da720440c7ac7d3564f33e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 13:14:44 +0200 Subject: [PATCH 10/11] zfs comment --- src-tauri/src/enterprise/inspector/linux.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/enterprise/inspector/linux.rs b/src-tauri/src/enterprise/inspector/linux.rs index a99fb3fe..bce09a52 100644 --- a/src-tauri/src/enterprise/inspector/linux.rs +++ b/src-tauri/src/enterprise/inspector/linux.rs @@ -64,6 +64,6 @@ fn check_luks() -> Result { // https://labex.io/tutorials/linux-how-to-check-if-disk-encryption-is-enabled-in-linux-558786 // FIXME: This will check all available disks, so if any is encrypted, it will succeed. pub(super) fn disk_encryption_status() -> Result { - // TODO: zfs encryption + // TODO: `zfs list -jo name,encryption,mountpoint` and check for `/` and `on`. check_luks() } From d3e6dda8a2ca9d05df4277e90147be46aeac4987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Tue, 12 May 2026 13:24:29 +0200 Subject: [PATCH 11/11] clippy fix --- src-tauri/src/enterprise/inspector/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/enterprise/inspector/mod.rs b/src-tauri/src/enterprise/inspector/mod.rs index 710a502a..424a2144 100644 --- a/src-tauri/src/enterprise/inspector/mod.rs +++ b/src-tauri/src/enterprise/inspector/mod.rs @@ -100,7 +100,7 @@ fn os_version() -> Result { fn linux_kernel_version() -> Result { #[cfg(target_os = "linux")] { - System::kernel_version().ok_or_else(|| UnavailableReason::DetectionFailed) + System::kernel_version().ok_or(UnavailableReason::DetectionFailed) } #[cfg(not(target_os = "linux"))]