From 65451f759d1c98b35eb4f88cbb85ec84bcdb9bb7 Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Mon, 27 Oct 2025 12:44:05 +0100 Subject: [PATCH 1/4] docs(node): describe analysis-related deployments --- pnpm-lock.yaml | 860 +++++++++++++------------ src/.vitepress/routes/sidebar/admin.ts | 3 +- src/guide/admin/analysis-definition.md | 392 +++++++++++ src/guide/admin/index.md | 4 +- 4 files changed, 860 insertions(+), 399 deletions(-) create mode 100644 src/guide/admin/analysis-definition.md diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdb1e5ec..9e2c1d16 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: dependencies: vite: - specifier: ^5.2.6 - version: 5.4.8 + specifier: ^5.4.11 + version: 5.4.21 vitepress: - specifier: ^1.3.0 - version: 1.4.0(@algolia/client-search@4.24.0)(postcss@8.4.47)(search-insights@2.17.2)(typescript@5.6.3) + specifier: ^1.5.0 + version: 1.6.4(@algolia/client-search@5.41.0)(postcss@8.5.6)(search-insights@2.17.2)(typescript@5.6.3) vitepress-plugin-search: specifier: ^1.0.4-alpha.22 - version: 1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.4.0(@algolia/client-search@4.24.0)(postcss@8.4.47)(search-insights@2.17.2)(typescript@5.6.3))(vue@3.5.11(typescript@5.6.3)) + version: 1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.6.4(@algolia/client-search@5.41.0)(postcss@8.5.6)(search-insights@2.17.2)(typescript@5.6.3))(vue@3.5.22(typescript@5.6.3)) devDependencies: '@tada5hi/eslint-config-vue-typescript': specifier: ^1.3.10 @@ -36,96 +36,107 @@ importers: packages: - '@algolia/autocomplete-core@1.9.3': - resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} + '@algolia/abtesting@1.7.0': + resolution: {integrity: sha512-hOEItTFOvNLI6QX6TSGu7VE4XcUcdoKZT8NwDY+5mWwu87rGhkjlY7uesKTInlg6Sh8cyRkDBYRumxbkoBbBhA==} + engines: {node: '>= 14.0.0'} - '@algolia/autocomplete-plugin-algolia-insights@1.9.3': - resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} + '@algolia/autocomplete-core@1.17.7': + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7': + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} peerDependencies: search-insights: '>= 1 < 3' - '@algolia/autocomplete-preset-algolia@1.9.3': - resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + '@algolia/autocomplete-preset-algolia@1.17.7': + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - '@algolia/autocomplete-shared@1.9.3': - resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + '@algolia/autocomplete-shared@1.17.7': + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - '@algolia/cache-browser-local-storage@4.24.0': - resolution: {integrity: sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==} - - '@algolia/cache-common@4.24.0': - resolution: {integrity: sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==} + '@algolia/client-abtesting@5.41.0': + resolution: {integrity: sha512-iRuvbEyuHCAhIMkyzG3tfINLxTS7mSKo7q8mQF+FbQpWenlAlrXnfZTN19LRwnVjx0UtAdZq96ThMWGS6cQ61A==} + engines: {node: '>= 14.0.0'} - '@algolia/cache-in-memory@4.24.0': - resolution: {integrity: sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==} + '@algolia/client-analytics@5.41.0': + resolution: {integrity: sha512-OIPVbGfx/AO8l1V70xYTPSeTt/GCXPEl6vQICLAXLCk9WOUbcLGcy6t8qv0rO7Z7/M/h9afY6Af8JcnI+FBFdQ==} + engines: {node: '>= 14.0.0'} - '@algolia/client-account@4.24.0': - resolution: {integrity: sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==} + '@algolia/client-common@5.41.0': + resolution: {integrity: sha512-8Mc9niJvfuO8dudWN5vSUlYkz7U3M3X3m1crDLc9N7FZrIVoNGOUETPk3TTHviJIh9y6eKZKbq1hPGoGY9fqPA==} + engines: {node: '>= 14.0.0'} - '@algolia/client-analytics@4.24.0': - resolution: {integrity: sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==} + '@algolia/client-insights@5.41.0': + resolution: {integrity: sha512-vXzvCGZS6Ixxn+WyzGUVDeR3HO/QO5POeeWy1kjNJbEf6f+tZSI+OiIU9Ha+T3ntV8oXFyBEuweygw4OLmgfiQ==} + engines: {node: '>= 14.0.0'} - '@algolia/client-common@4.24.0': - resolution: {integrity: sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==} + '@algolia/client-personalization@5.41.0': + resolution: {integrity: sha512-tkymXhmlcc7w/HEvLRiHcpHxLFcUB+0PnE9FcG6hfFZ1ZXiWabH+sX+uukCVnluyhfysU9HRU2kUmUWfucx1Dg==} + engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@4.24.0': - resolution: {integrity: sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==} + '@algolia/client-query-suggestions@5.41.0': + resolution: {integrity: sha512-vyXDoz3kEZnosNeVQQwf0PbBt5IZJoHkozKRIsYfEVm+ylwSDFCW08qy2YIVSHdKy69/rWN6Ue/6W29GgVlmKQ==} + engines: {node: '>= 14.0.0'} - '@algolia/client-search@4.24.0': - resolution: {integrity: sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==} + '@algolia/client-search@5.41.0': + resolution: {integrity: sha512-G9I2atg1ShtFp0t7zwleP6aPS4DcZvsV4uoQOripp16aR6VJzbEnKFPLW4OFXzX7avgZSpYeBAS+Zx4FOgmpPw==} + engines: {node: '>= 14.0.0'} - '@algolia/logger-common@4.24.0': - resolution: {integrity: sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==} + '@algolia/ingestion@1.41.0': + resolution: {integrity: sha512-sxU/ggHbZtmrYzTkueTXXNyifn+ozsLP+Wi9S2hOBVhNWPZ8uRiDTDcFyL7cpCs1q72HxPuhzTP5vn4sUl74cQ==} + engines: {node: '>= 14.0.0'} - '@algolia/logger-console@4.24.0': - resolution: {integrity: sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==} + '@algolia/monitoring@1.41.0': + resolution: {integrity: sha512-UQ86R6ixraHUpd0hn4vjgTHbViNO8+wA979gJmSIsRI3yli2v89QSFF/9pPcADR6PbtSio/99PmSNxhZy+CR3Q==} + engines: {node: '>= 14.0.0'} - '@algolia/recommend@4.24.0': - resolution: {integrity: sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==} + '@algolia/recommend@5.41.0': + resolution: {integrity: sha512-DxP9P8jJ8whJOnvmyA5mf1wv14jPuI0L25itGfOHSU6d4ZAjduVfPjTS3ROuUN5CJoTdlidYZE+DtfWHxJwyzQ==} + engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@4.24.0': - resolution: {integrity: sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==} + '@algolia/requester-browser-xhr@5.41.0': + resolution: {integrity: sha512-C21J+LYkE48fDwtLX7YXZd2Fn7Fe0/DOEtvohSfr/ODP8dGDhy9faaYeWB0n1AvmZltugjkjAXT7xk0CYNIXsQ==} + engines: {node: '>= 14.0.0'} - '@algolia/requester-common@4.24.0': - resolution: {integrity: sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==} + '@algolia/requester-fetch@5.41.0': + resolution: {integrity: sha512-FhJy/+QJhMx1Hajf2LL8og4J7SqOAHiAuUXq27cct4QnPhSIuIGROzeRpfDNH5BUbq22UlMuGd44SeD4HRAqvA==} + engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@4.24.0': - resolution: {integrity: sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==} + '@algolia/requester-node-http@5.41.0': + resolution: {integrity: sha512-tYv3rGbhBS0eZ5D8oCgV88iuWILROiemk+tQ3YsAKZv2J4kKUNvKkrX/If/SreRy4MGP2uJzMlyKcfSfO2mrsQ==} + engines: {node: '>= 14.0.0'} - '@algolia/transporter@4.24.0': - resolution: {integrity: sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==} - - '@babel/helper-string-parser@7.25.7': - resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.7': - resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/parser@7.25.7': - resolution: {integrity: sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/types@7.25.7': - resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@docsearch/css@3.6.2': - resolution: {integrity: sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw==} + '@docsearch/css@3.8.2': + resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} - '@docsearch/js@3.6.2': - resolution: {integrity: sha512-pS4YZF+VzUogYrkblCucQ0Oy2m8Wggk8Kk7lECmZM60hTbaydSIhJTTiCrmoxtBqV8wxORnOqcqqOfbmkkQEcA==} + '@docsearch/js@3.8.2': + resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} - '@docsearch/react@3.6.2': - resolution: {integrity: sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==} + '@docsearch/react@3.8.2': + resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -310,12 +321,18 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@iconify-json/simple-icons@1.2.55': + resolution: {integrity: sha512-9vc04pmup/zcef8hDypWU8nMwMaFVkWuUzWkxyL++DVp5AA8baoJHK6RyKN1v+cvfR2agxkUb053XVggzFFkTA==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -416,23 +433,29 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@shikijs/core@1.22.0': - resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==} + '@shikijs/core@2.5.0': + resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==} + + '@shikijs/engine-javascript@2.5.0': + resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==} + + '@shikijs/engine-oniguruma@2.5.0': + resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==} - '@shikijs/engine-javascript@1.22.0': - resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==} + '@shikijs/langs@2.5.0': + resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==} - '@shikijs/engine-oniguruma@1.22.0': - resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==} + '@shikijs/themes@2.5.0': + resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==} - '@shikijs/transformers@1.22.0': - resolution: {integrity: sha512-k7iMOYuGQA62KwAuJOQBgH2IQb5vP8uiB3lMvAMGUgAMMurePOx3Z7oNqJdcpxqZP6I9cc7nc4DNqSKduCxmdg==} + '@shikijs/transformers@2.5.0': + resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==} - '@shikijs/types@1.22.0': - resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==} + '@shikijs/types@2.5.0': + resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==} - '@shikijs/vscode-textmate@9.3.0': - resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} '@tada5hi/eslint-config-typescript@1.2.12': resolution: {integrity: sha512-YCsmqxCLAx3Qqeq1oRf6HN05O8Zoa/O2jwLHZHiNnVFki0UY7l61hEGMRZ1F+PcAyVm5BtlmxNgyiMsFy0SMXA==} @@ -478,8 +501,8 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/web-bluetooth@0.0.20': - resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} '@typescript-eslint/eslint-plugin@7.18.0': resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} @@ -542,56 +565,56 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-vue@5.1.4': - resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==} + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 vue: ^3.2.25 - '@vue/compiler-core@3.5.11': - resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==} + '@vue/compiler-core@3.5.22': + resolution: {integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==} - '@vue/compiler-dom@3.5.11': - resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==} + '@vue/compiler-dom@3.5.22': + resolution: {integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==} - '@vue/compiler-sfc@3.5.11': - resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==} + '@vue/compiler-sfc@3.5.22': + resolution: {integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==} - '@vue/compiler-ssr@3.5.11': - resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==} + '@vue/compiler-ssr@3.5.22': + resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==} - '@vue/devtools-api@7.4.6': - resolution: {integrity: sha512-XipBV5k0/IfTr0sNBDTg7OBUCp51cYMMXyPxLXJZ4K/wmUeMqt8cVdr2ZZGOFq+si/jTyCYnNxeKoyev5DOUUA==} + '@vue/devtools-api@7.7.7': + resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==} - '@vue/devtools-kit@7.4.6': - resolution: {integrity: sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==} + '@vue/devtools-kit@7.7.7': + resolution: {integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==} - '@vue/devtools-shared@7.4.6': - resolution: {integrity: sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==} + '@vue/devtools-shared@7.7.7': + resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==} - '@vue/reactivity@3.5.11': - resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==} + '@vue/reactivity@3.5.22': + resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==} - '@vue/runtime-core@3.5.11': - resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==} + '@vue/runtime-core@3.5.22': + resolution: {integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==} - '@vue/runtime-dom@3.5.11': - resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==} + '@vue/runtime-dom@3.5.22': + resolution: {integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==} - '@vue/server-renderer@3.5.11': - resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==} + '@vue/server-renderer@3.5.22': + resolution: {integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==} peerDependencies: - vue: 3.5.11 + vue: 3.5.22 - '@vue/shared@3.5.11': - resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==} + '@vue/shared@3.5.22': + resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==} - '@vueuse/core@11.1.0': - resolution: {integrity: sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==} + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} - '@vueuse/integrations@11.1.0': - resolution: {integrity: sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==} + '@vueuse/integrations@12.8.2': + resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==} peerDependencies: async-validator: ^4 axios: ^1 @@ -631,11 +654,11 @@ packages: universal-cookie: optional: true - '@vueuse/metadata@11.1.0': - resolution: {integrity: sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==} + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} - '@vueuse/shared@11.1.0': - resolution: {integrity: sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==} + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -650,8 +673,9 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - algoliasearch@4.24.0: - resolution: {integrity: sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==} + algoliasearch@5.41.0: + resolution: {integrity: sha512-9E4b3rJmYbBkn7e3aAPt1as+VVnRhsR4qwRRgOzpeyz4PAOuwKh0HI4AN6mTrqK0S0M9fCCSTOUnuJ8gPY/tvA==} + engines: {node: '>= 14.0.0'} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -707,8 +731,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - birpc@0.2.19: - resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + birpc@2.6.1: + resolution: {integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -760,9 +784,9 @@ packages: confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - copy-anything@3.0.5: - resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} - engines: {node: '>=12.13'} + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -838,6 +862,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1060,8 +1087,8 @@ packages: flexsearch@0.7.43: resolution: {integrity: sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==} - focus-trap@7.6.0: - resolution: {integrity: sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ==} + focus-trap@7.6.6: + resolution: {integrity: sha512-v/Z8bvMCajtx4mEXmOo7QEsIzlIOqRXTIwgUfsFOF9gEsespdbD0AkPIka1bSXZ8Y8oZ+2IVDQZePkTfEHZl7Q==} for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -1166,8 +1193,8 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hast-util-to-html@9.0.3: - resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} @@ -1282,9 +1309,9 @@ packages: is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-what@4.1.16: - resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} - engines: {node: '>=12.13'} + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -1337,8 +1364,8 @@ packages: resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==} engines: {node: 20 || >=22} - magic-string@0.30.11: - resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} @@ -1394,8 +1421,8 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - minisearch@7.1.0: - resolution: {integrity: sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==} + minisearch@7.2.0: + resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==} mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} @@ -1403,6 +1430,11 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1445,8 +1477,8 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - oniguruma-to-js@0.4.3: - resolution: {integrity: sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==} + oniguruma-to-es@3.1.1: + resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} @@ -1496,6 +1528,9 @@ packages: picocolors@1.1.0: resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -1512,6 +1547,10 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + preact@10.24.2: resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} @@ -1519,8 +1558,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - property-information@6.5.0: - resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -1529,8 +1568,14 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - regex@4.3.3: - resolution: {integrity: sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==} + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.0.1: + resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} regexp.prototype.flags@1.5.3: resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} @@ -1612,8 +1657,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@1.22.0: - resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==} + shiki@2.5.0: + resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -1676,8 +1721,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - superjson@2.2.1: - resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} + superjson@2.2.3: + resolution: {integrity: sha512-ay3d+LW/S6yppKoTz3Bq4mG0xrS5bFwfWEBmQfbC7lt5wmtk+Obq0TxVuA9eYRirBTQb1K3eEpBRHMQEo0WyVw==} engines: {node: '>=16'} supports-color@7.2.0: @@ -1688,8 +1733,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tabbable@6.3.0: + resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==} tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} @@ -1698,10 +1743,6 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1780,8 +1821,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@5.4.8: - resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -1819,8 +1860,8 @@ packages: vitepress: ^1.0.0-rc.35 vue: '3' - vitepress@1.4.0: - resolution: {integrity: sha512-JXCv4EsKTDyAFb6C/UjZr7nsGAzZ6mafVk2rx7rG5o8N+B/4QstIk+iEOe/9dKoU6V624UIC6g1pZ+K63rxhlw==} + vitepress@1.6.4: + resolution: {integrity: sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==} hasBin: true peerDependencies: markdown-it-mathjax3: ^4 @@ -1831,25 +1872,14 @@ packages: postcss: optional: true - vue-demi@0.14.10: - resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} - engines: {node: '>=12'} - hasBin: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - vue-eslint-parser@9.4.3: resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' - vue@3.5.11: - resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==} + vue@3.5.22: + resolution: {integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -1896,129 +1926,136 @@ packages: snapshots: - '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)(search-insights@2.17.2)': + '@algolia/abtesting@1.7.0': dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)(search-insights@2.17.2) - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0) + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 + + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.2)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.2) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights - '@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)(search-insights@2.17.2)': + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.2)': dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) search-insights: 2.17.2 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - '@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)': + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)': dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0) - '@algolia/client-search': 4.24.0 - algoliasearch: 4.24.0 + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) + '@algolia/client-search': 5.41.0 + algoliasearch: 5.41.0 - '@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)': + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)': dependencies: - '@algolia/client-search': 4.24.0 - algoliasearch: 4.24.0 + '@algolia/client-search': 5.41.0 + algoliasearch: 5.41.0 - '@algolia/cache-browser-local-storage@4.24.0': + '@algolia/client-abtesting@5.41.0': dependencies: - '@algolia/cache-common': 4.24.0 - - '@algolia/cache-common@4.24.0': {} + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/cache-in-memory@4.24.0': + '@algolia/client-analytics@5.41.0': dependencies: - '@algolia/cache-common': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/client-account@4.24.0': - dependencies: - '@algolia/client-common': 4.24.0 - '@algolia/client-search': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common@5.41.0': {} - '@algolia/client-analytics@4.24.0': + '@algolia/client-insights@5.41.0': dependencies: - '@algolia/client-common': 4.24.0 - '@algolia/client-search': 4.24.0 - '@algolia/requester-common': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/client-common@4.24.0': + '@algolia/client-personalization@5.41.0': dependencies: - '@algolia/requester-common': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/client-personalization@4.24.0': + '@algolia/client-query-suggestions@5.41.0': dependencies: - '@algolia/client-common': 4.24.0 - '@algolia/requester-common': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/client-search@4.24.0': + '@algolia/client-search@5.41.0': dependencies: - '@algolia/client-common': 4.24.0 - '@algolia/requester-common': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/logger-common@4.24.0': {} - - '@algolia/logger-console@4.24.0': + '@algolia/ingestion@1.41.0': dependencies: - '@algolia/logger-common': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/recommend@4.24.0': + '@algolia/monitoring@1.41.0': dependencies: - '@algolia/cache-browser-local-storage': 4.24.0 - '@algolia/cache-common': 4.24.0 - '@algolia/cache-in-memory': 4.24.0 - '@algolia/client-common': 4.24.0 - '@algolia/client-search': 4.24.0 - '@algolia/logger-common': 4.24.0 - '@algolia/logger-console': 4.24.0 - '@algolia/requester-browser-xhr': 4.24.0 - '@algolia/requester-common': 4.24.0 - '@algolia/requester-node-http': 4.24.0 - '@algolia/transporter': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/requester-browser-xhr@4.24.0': + '@algolia/recommend@5.41.0': dependencies: - '@algolia/requester-common': 4.24.0 + '@algolia/client-common': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 - '@algolia/requester-common@4.24.0': {} + '@algolia/requester-browser-xhr@5.41.0': + dependencies: + '@algolia/client-common': 5.41.0 - '@algolia/requester-node-http@4.24.0': + '@algolia/requester-fetch@5.41.0': dependencies: - '@algolia/requester-common': 4.24.0 + '@algolia/client-common': 5.41.0 - '@algolia/transporter@4.24.0': + '@algolia/requester-node-http@5.41.0': dependencies: - '@algolia/cache-common': 4.24.0 - '@algolia/logger-common': 4.24.0 - '@algolia/requester-common': 4.24.0 + '@algolia/client-common': 5.41.0 - '@babel/helper-string-parser@7.25.7': {} + '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.25.7': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/parser@7.25.7': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.25.7 + '@babel/types': 7.28.5 - '@babel/types@7.25.7': + '@babel/types@7.28.5': dependencies: - '@babel/helper-string-parser': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - '@docsearch/css@3.6.2': {} + '@docsearch/css@3.8.2': {} - '@docsearch/js@3.6.2(@algolia/client-search@4.24.0)(search-insights@2.17.2)': + '@docsearch/js@3.8.2(@algolia/client-search@5.41.0)(search-insights@2.17.2)': dependencies: - '@docsearch/react': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.17.2) + '@docsearch/react': 3.8.2(@algolia/client-search@5.41.0)(search-insights@2.17.2) preact: 10.24.2 transitivePeerDependencies: - '@algolia/client-search' @@ -2027,12 +2064,12 @@ snapshots: - react-dom - search-insights - '@docsearch/react@3.6.2(@algolia/client-search@4.24.0)(search-insights@2.17.2)': + '@docsearch/react@3.8.2(@algolia/client-search@5.41.0)(search-insights@2.17.2)': dependencies: - '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0)(search-insights@2.17.2) - '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.24.0)(algoliasearch@4.24.0) - '@docsearch/css': 3.6.2 - algoliasearch: 4.24.0 + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.2) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) + '@docsearch/css': 3.8.2 + algoliasearch: 5.41.0 optionalDependencies: search-insights: 2.17.2 transitivePeerDependencies: @@ -2142,6 +2179,12 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@iconify-json/simple-icons@1.2.55': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -2151,7 +2194,7 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -2217,36 +2260,45 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@shikijs/core@1.22.0': + '@shikijs/core@2.5.0': dependencies: - '@shikijs/engine-javascript': 1.22.0 - '@shikijs/engine-oniguruma': 1.22.0 - '@shikijs/types': 1.22.0 - '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - hast-util-to-html: 9.0.3 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 3.1.1 - '@shikijs/engine-javascript@1.22.0': + '@shikijs/engine-oniguruma@2.5.0': dependencies: - '@shikijs/types': 1.22.0 - '@shikijs/vscode-textmate': 9.3.0 - oniguruma-to-js: 0.4.3 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/engine-oniguruma@1.22.0': + '@shikijs/langs@2.5.0': dependencies: - '@shikijs/types': 1.22.0 - '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/types': 2.5.0 - '@shikijs/transformers@1.22.0': + '@shikijs/themes@2.5.0': dependencies: - shiki: 1.22.0 + '@shikijs/types': 2.5.0 - '@shikijs/types@1.22.0': + '@shikijs/transformers@2.5.0': dependencies: - '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/core': 2.5.0 + '@shikijs/types': 2.5.0 + + '@shikijs/types@2.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - '@shikijs/vscode-textmate@9.3.0': {} + '@shikijs/vscode-textmate@10.0.2': {} '@tada5hi/eslint-config-typescript@1.2.12(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1)(typescript@5.6.3)': dependencies: @@ -2333,7 +2385,7 @@ snapshots: '@types/unist@3.0.3': {} - '@types/web-bluetooth@0.0.20': {} + '@types/web-bluetooth@0.0.21': {} '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': dependencies: @@ -2418,112 +2470,109 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-vue@5.1.4(vite@5.4.8)(vue@3.5.11(typescript@5.6.3))': + '@vitejs/plugin-vue@5.2.4(vite@5.4.21)(vue@3.5.22(typescript@5.6.3))': dependencies: - vite: 5.4.8 - vue: 3.5.11(typescript@5.6.3) + vite: 5.4.21 + vue: 3.5.22(typescript@5.6.3) - '@vue/compiler-core@3.5.11': + '@vue/compiler-core@3.5.22': dependencies: - '@babel/parser': 7.25.7 - '@vue/shared': 3.5.11 + '@babel/parser': 7.28.5 + '@vue/shared': 3.5.22 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.11': + '@vue/compiler-dom@3.5.22': dependencies: - '@vue/compiler-core': 3.5.11 - '@vue/shared': 3.5.11 + '@vue/compiler-core': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/compiler-sfc@3.5.11': + '@vue/compiler-sfc@3.5.22': dependencies: - '@babel/parser': 7.25.7 - '@vue/compiler-core': 3.5.11 - '@vue/compiler-dom': 3.5.11 - '@vue/compiler-ssr': 3.5.11 - '@vue/shared': 3.5.11 + '@babel/parser': 7.28.5 + '@vue/compiler-core': 3.5.22 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 estree-walker: 2.0.2 - magic-string: 0.30.11 - postcss: 8.4.47 + magic-string: 0.30.21 + postcss: 8.5.6 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.11': + '@vue/compiler-ssr@3.5.22': dependencies: - '@vue/compiler-dom': 3.5.11 - '@vue/shared': 3.5.11 + '@vue/compiler-dom': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/devtools-api@7.4.6': + '@vue/devtools-api@7.7.7': dependencies: - '@vue/devtools-kit': 7.4.6 + '@vue/devtools-kit': 7.7.7 - '@vue/devtools-kit@7.4.6': + '@vue/devtools-kit@7.7.7': dependencies: - '@vue/devtools-shared': 7.4.6 - birpc: 0.2.19 + '@vue/devtools-shared': 7.7.7 + birpc: 2.6.1 hookable: 5.5.3 mitt: 3.0.1 perfect-debounce: 1.0.0 speakingurl: 14.0.1 - superjson: 2.2.1 + superjson: 2.2.3 - '@vue/devtools-shared@7.4.6': + '@vue/devtools-shared@7.7.7': dependencies: rfdc: 1.4.1 - '@vue/reactivity@3.5.11': + '@vue/reactivity@3.5.22': dependencies: - '@vue/shared': 3.5.11 + '@vue/shared': 3.5.22 - '@vue/runtime-core@3.5.11': + '@vue/runtime-core@3.5.22': dependencies: - '@vue/reactivity': 3.5.11 - '@vue/shared': 3.5.11 + '@vue/reactivity': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/runtime-dom@3.5.11': + '@vue/runtime-dom@3.5.22': dependencies: - '@vue/reactivity': 3.5.11 - '@vue/runtime-core': 3.5.11 - '@vue/shared': 3.5.11 + '@vue/reactivity': 3.5.22 + '@vue/runtime-core': 3.5.22 + '@vue/shared': 3.5.22 csstype: 3.1.3 - '@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.3))': + '@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.6.3))': dependencies: - '@vue/compiler-ssr': 3.5.11 - '@vue/shared': 3.5.11 - vue: 3.5.11(typescript@5.6.3) + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 + vue: 3.5.22(typescript@5.6.3) - '@vue/shared@3.5.11': {} + '@vue/shared@3.5.22': {} - '@vueuse/core@11.1.0(vue@3.5.11(typescript@5.6.3))': + '@vueuse/core@12.8.2(typescript@5.6.3)': dependencies: - '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 11.1.0 - '@vueuse/shared': 11.1.0(vue@3.5.11(typescript@5.6.3)) - vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.3)) + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.6.3) + vue: 3.5.22(typescript@5.6.3) transitivePeerDependencies: - - '@vue/composition-api' - - vue + - typescript - '@vueuse/integrations@11.1.0(focus-trap@7.6.0)(vue@3.5.11(typescript@5.6.3))': + '@vueuse/integrations@12.8.2(focus-trap@7.6.6)(typescript@5.6.3)': dependencies: - '@vueuse/core': 11.1.0(vue@3.5.11(typescript@5.6.3)) - '@vueuse/shared': 11.1.0(vue@3.5.11(typescript@5.6.3)) - vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.3)) + '@vueuse/core': 12.8.2(typescript@5.6.3) + '@vueuse/shared': 12.8.2(typescript@5.6.3) + vue: 3.5.22(typescript@5.6.3) optionalDependencies: - focus-trap: 7.6.0 + focus-trap: 7.6.6 transitivePeerDependencies: - - '@vue/composition-api' - - vue + - typescript - '@vueuse/metadata@11.1.0': {} + '@vueuse/metadata@12.8.2': {} - '@vueuse/shared@11.1.0(vue@3.5.11(typescript@5.6.3))': + '@vueuse/shared@12.8.2(typescript@5.6.3)': dependencies: - vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.3)) + vue: 3.5.22(typescript@5.6.3) transitivePeerDependencies: - - '@vue/composition-api' - - vue + - typescript acorn-jsx@5.3.2(acorn@8.12.1): dependencies: @@ -2538,23 +2587,22 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - algoliasearch@4.24.0: - dependencies: - '@algolia/cache-browser-local-storage': 4.24.0 - '@algolia/cache-common': 4.24.0 - '@algolia/cache-in-memory': 4.24.0 - '@algolia/client-account': 4.24.0 - '@algolia/client-analytics': 4.24.0 - '@algolia/client-common': 4.24.0 - '@algolia/client-personalization': 4.24.0 - '@algolia/client-search': 4.24.0 - '@algolia/logger-common': 4.24.0 - '@algolia/logger-console': 4.24.0 - '@algolia/recommend': 4.24.0 - '@algolia/requester-browser-xhr': 4.24.0 - '@algolia/requester-common': 4.24.0 - '@algolia/requester-node-http': 4.24.0 - '@algolia/transporter': 4.24.0 + algoliasearch@5.41.0: + dependencies: + '@algolia/abtesting': 1.7.0 + '@algolia/client-abtesting': 5.41.0 + '@algolia/client-analytics': 5.41.0 + '@algolia/client-common': 5.41.0 + '@algolia/client-insights': 5.41.0 + '@algolia/client-personalization': 5.41.0 + '@algolia/client-query-suggestions': 5.41.0 + '@algolia/client-search': 5.41.0 + '@algolia/ingestion': 1.41.0 + '@algolia/monitoring': 1.41.0 + '@algolia/recommend': 5.41.0 + '@algolia/requester-browser-xhr': 5.41.0 + '@algolia/requester-fetch': 5.41.0 + '@algolia/requester-node-http': 5.41.0 ansi-regex@5.0.1: {} @@ -2624,7 +2672,7 @@ snapshots: balanced-match@1.0.2: {} - birpc@0.2.19: {} + birpc@2.6.1: {} boolbase@1.0.0: {} @@ -2674,9 +2722,9 @@ snapshots: confusing-browser-globals@1.0.11: {} - copy-anything@3.0.5: + copy-anything@4.0.5: dependencies: - is-what: 4.1.16 + is-what: 5.5.0 cross-spawn@7.0.3: dependencies: @@ -2748,6 +2796,8 @@ snapshots: eastasianwidth@0.2.0: {} + emoji-regex-xs@1.0.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -3100,9 +3150,9 @@ snapshots: flexsearch@0.7.43: {} - focus-trap@7.6.0: + focus-trap@7.6.6: dependencies: - tabbable: 6.2.0 + tabbable: 6.3.0 for-each@0.3.3: dependencies: @@ -3221,7 +3271,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hast-util-to-html@9.0.3: + hast-util-to-html@9.0.5: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 @@ -3230,7 +3280,7 @@ snapshots: hast-util-whitespace: 3.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.2.0 - property-information: 6.5.0 + property-information: 7.1.0 space-separated-tokens: 2.0.2 stringify-entities: 4.0.4 zwitch: 2.0.4 @@ -3340,7 +3390,7 @@ snapshots: dependencies: call-bind: 1.0.7 - is-what@4.1.16: {} + is-what@5.5.0: {} isarray@2.0.5: {} @@ -3387,9 +3437,9 @@ snapshots: lru-cache@11.0.1: {} - magic-string@0.30.11: + magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 mark.js@8.11.1: {} @@ -3455,12 +3505,14 @@ snapshots: minipass@7.1.2: {} - minisearch@7.1.0: {} + minisearch@7.2.0: {} mitt@3.0.1: {} ms@2.1.3: {} + nanoid@3.3.11: {} + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -3509,9 +3561,11 @@ snapshots: dependencies: wrappy: 1.0.2 - oniguruma-to-js@0.4.3: + oniguruma-to-es@3.1.1: dependencies: - regex: 4.3.3 + emoji-regex-xs: 1.0.0 + regex: 6.0.1 + regex-recursion: 6.0.2 optionator@0.9.4: dependencies: @@ -3555,6 +3609,8 @@ snapshots: picocolors@1.1.0: {} + picocolors@1.1.1: {} + picomatch@2.3.1: {} possible-typed-array-names@1.0.0: {} @@ -3570,17 +3626,31 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + preact@10.24.2: {} prelude-ls@1.2.1: {} - property-information@6.5.0: {} + property-information@7.1.0: {} punycode@2.3.1: {} queue-microtask@1.2.3: {} - regex@4.3.3: {} + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.0.1: + dependencies: + regex-utilities: 2.3.0 regexp.prototype.flags@1.5.3: dependencies: @@ -3681,13 +3751,15 @@ snapshots: shebang-regex@3.0.0: {} - shiki@1.22.0: + shiki@2.5.0: dependencies: - '@shikijs/core': 1.22.0 - '@shikijs/engine-javascript': 1.22.0 - '@shikijs/engine-oniguruma': 1.22.0 - '@shikijs/types': 1.22.0 - '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/core': 2.5.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/langs': 2.5.0 + '@shikijs/themes': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 side-channel@1.0.6: @@ -3755,9 +3827,9 @@ snapshots: strip-json-comments@3.1.1: {} - superjson@2.2.1: + superjson@2.2.3: dependencies: - copy-anything: 3.0.5 + copy-anything: 4.0.5 supports-color@7.2.0: dependencies: @@ -3765,14 +3837,12 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tabbable@6.2.0: {} + tabbable@6.3.0: {} tapable@2.2.1: {} text-table@0.2.0: {} - to-fast-properties@2.0.0: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -3878,7 +3948,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@5.4.8: + vite@5.4.21: dependencies: esbuild: 0.21.5 postcss: 8.4.47 @@ -3886,42 +3956,42 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - vitepress-plugin-search@1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.4.0(@algolia/client-search@4.24.0)(postcss@8.4.47)(search-insights@2.17.2)(typescript@5.6.3))(vue@3.5.11(typescript@5.6.3)): + vitepress-plugin-search@1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.6.4(@algolia/client-search@5.41.0)(postcss@8.5.6)(search-insights@2.17.2)(typescript@5.6.3))(vue@3.5.22(typescript@5.6.3)): dependencies: '@types/flexsearch': 0.7.6 '@types/markdown-it': 12.2.3 flexsearch: 0.7.43 glob-to-regexp: 0.4.1 markdown-it: 13.0.2 - vitepress: 1.4.0(@algolia/client-search@4.24.0)(postcss@8.4.47)(search-insights@2.17.2)(typescript@5.6.3) - vue: 3.5.11(typescript@5.6.3) + vitepress: 1.6.4(@algolia/client-search@5.41.0)(postcss@8.5.6)(search-insights@2.17.2)(typescript@5.6.3) + vue: 3.5.22(typescript@5.6.3) - vitepress@1.4.0(@algolia/client-search@4.24.0)(postcss@8.4.47)(search-insights@2.17.2)(typescript@5.6.3): + vitepress@1.6.4(@algolia/client-search@5.41.0)(postcss@8.5.6)(search-insights@2.17.2)(typescript@5.6.3): dependencies: - '@docsearch/css': 3.6.2 - '@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.17.2) - '@shikijs/core': 1.22.0 - '@shikijs/transformers': 1.22.0 - '@shikijs/types': 1.22.0 + '@docsearch/css': 3.8.2 + '@docsearch/js': 3.8.2(@algolia/client-search@5.41.0)(search-insights@2.17.2) + '@iconify-json/simple-icons': 1.2.55 + '@shikijs/core': 2.5.0 + '@shikijs/transformers': 2.5.0 + '@shikijs/types': 2.5.0 '@types/markdown-it': 14.1.2 - '@vitejs/plugin-vue': 5.1.4(vite@5.4.8)(vue@3.5.11(typescript@5.6.3)) - '@vue/devtools-api': 7.4.6 - '@vue/shared': 3.5.11 - '@vueuse/core': 11.1.0(vue@3.5.11(typescript@5.6.3)) - '@vueuse/integrations': 11.1.0(focus-trap@7.6.0)(vue@3.5.11(typescript@5.6.3)) - focus-trap: 7.6.0 + '@vitejs/plugin-vue': 5.2.4(vite@5.4.21)(vue@3.5.22(typescript@5.6.3)) + '@vue/devtools-api': 7.7.7 + '@vue/shared': 3.5.22 + '@vueuse/core': 12.8.2(typescript@5.6.3) + '@vueuse/integrations': 12.8.2(focus-trap@7.6.6)(typescript@5.6.3) + focus-trap: 7.6.6 mark.js: 8.11.1 - minisearch: 7.1.0 - shiki: 1.22.0 - vite: 5.4.8 - vue: 3.5.11(typescript@5.6.3) + minisearch: 7.2.0 + shiki: 2.5.0 + vite: 5.4.21 + vue: 3.5.22(typescript@5.6.3) optionalDependencies: - postcss: 8.4.47 + postcss: 8.5.6 transitivePeerDependencies: - '@algolia/client-search' - '@types/node' - '@types/react' - - '@vue/composition-api' - async-validator - axios - change-case @@ -3945,10 +4015,6 @@ snapshots: - typescript - universal-cookie - vue-demi@0.14.10(vue@3.5.11(typescript@5.6.3)): - dependencies: - vue: 3.5.11(typescript@5.6.3) - vue-eslint-parser@9.4.3(eslint@8.57.1): dependencies: debug: 4.3.7 @@ -3962,13 +4028,13 @@ snapshots: transitivePeerDependencies: - supports-color - vue@3.5.11(typescript@5.6.3): + vue@3.5.22(typescript@5.6.3): dependencies: - '@vue/compiler-dom': 3.5.11 - '@vue/compiler-sfc': 3.5.11 - '@vue/runtime-dom': 3.5.11 - '@vue/server-renderer': 3.5.11(vue@3.5.11(typescript@5.6.3)) - '@vue/shared': 3.5.11 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-sfc': 3.5.22 + '@vue/runtime-dom': 3.5.22 + '@vue/server-renderer': 3.5.22(vue@3.5.22(typescript@5.6.3)) + '@vue/shared': 3.5.22 optionalDependencies: typescript: 5.6.3 diff --git a/src/.vitepress/routes/sidebar/admin.ts b/src/.vitepress/routes/sidebar/admin.ts index 02115d4c..910f9ce6 100644 --- a/src/.vitepress/routes/sidebar/admin.ts +++ b/src/.vitepress/routes/sidebar/admin.ts @@ -29,7 +29,8 @@ export const adminRoutes = [ {text: 'Bucket Setup for Data Store', link: '/bucket-setup-for-data-store'}, {text: 'Data Store Management', link: '/data-store-management'}, {text: 'Analysis Execution', link: '/analysis-execution'}, - {text: 'Keycloak & Access Control', link: '/keycloak-access-control'} + {text: 'Keycloak & Access Control', link: '/keycloak-access-control'}, + {text: 'Analysis Definition in k8s', link: '/analysis-definition'}, ] }, ] diff --git a/src/guide/admin/analysis-definition.md b/src/guide/admin/analysis-definition.md new file mode 100644 index 00000000..c8204174 --- /dev/null +++ b/src/guide/admin/analysis-definition.md @@ -0,0 +1,392 @@ +# Analysis Definition in Kubernetes + +As the administrator of your FLAME Node, it is important to understand how the analyses are being deployed on your system. While the [publicly available helm chart for the FLAME Node](https://github.com/PrivateAIM/helm/tree/master/charts/flame-node) makes it easy to see exactly how the components are defined, the analyses themselves are deployed using the Pod Orchestrator using the [Python kubernetes library](https://github.com/kubernetes-client/python) making it more difficult to quickly assess their configuration. This page covers the various kubernetes resources that are deployed when an analysis is started and well as how certain parameters can be modified to fit your security requirements. + +Here is a brief overview of the resources that are deployed when initiating an analysis: + +* [Analysis Deployment](#analysis-deployment) + * Analysis ReplicaSet + * Analysis Pod +* [Nginx Deployment](#nginx-deployment) + * Nginx ReplicaSet + * Nginx Pod +* [Services](#services) +* [ConfigMap](#configmap) +* [NetworkPolicy](#network-policy) + +## Deployments +When a FLAME Analysis is started, the Pod Orchestrator service creates two separate deployments: one for the analysis itself, and one for a nginx instance. Both are required for the analysis to be able to run and transmit its results, but as shown below, both have very stringent policies in place to severely limit their traffic. + +Each [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) is so configured to create a [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) which is responsible for maintaining a specified number of [Pod](https://kubernetes.io/docs/concepts/workloads/pods/) replicas at any given time. By using deployments, the workload can be better managed, and also allow one to monitor the state of the rollout and scale the workload as needed. Additionally, this template enables the use of [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) which are subsequently used to apply a restrictive [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to the generated Pods thus controlling the traffic in and out of the analysis container. + +### Analysis Deployment +Though the code for each analysis is manually reviewed and approved prior to running on any node, precautions are still taken to lock down all traffic both entering and leaving the Pod in which it is running in the kubernetes cluster. By default, every analysis deployed by the Pod Orchestrator has a restrictive Network Policy (see [NetworkPolicy](#network-policy) below) applied to it using the labels and selectors. + +However, the analysis cannot run in complete isolation since it still requires access to the data and needs to communicate with other FLAME components for sending progress updates and the results. In order to control its communication, a Nginx sidecar container is deployed in parallel with the analysis which serves as a proxy for all requests into and exiting the container. Details on how this Nginx sidecar controls traffic is discussed in the [Nginx Deployment](#nginx-deployment) section. + +An additional security measure to ensure that the analysis pod was created using the FLAME pipeline is verification using the OIDC protocol and the included Keycloak instance. Keycloak serves as an identity provider (IDP) to check whether requests made by certain components or services are who they say they are by bundling a JSON Web Token (JWT) with their request. Our software registers the FLAME services with Keycloak upon deployment and communication is authenticated using the OAuth2 endpoints. + +When an analysis is deployed via the FLAME UI or gateway, the Pod Orchestrator first verifies that the request came from an official FLAME component by checking the included JWT against Keycloak, and if authenticated, proceeds to register a new client within Keycloak. This registration process generates a token that is included in the analysis deployment and is subsequently used for retrieving a JWT from Keycloak that is included in all of its sent requests, including those sent for accessing the desired protected data being shared by your organization. + + +#### Template +Each analysis deployment can be defined with the following template: +```yaml +kind: Deployment +apiVersion: apps/v1 +metadata: + name: + namespace: default + labels: + app: + component: flame-analysis +spec: + replicas: 1 + selector: + matchLabels: + app: + component: flame-analysis + template: + metadata: + labels: + app: + component: flame-analysis + spec: + containers: + - name: + image: + ports: + - containerPort: 8000 + protocol: TCP + env: + - name: DATA_SOURCE_TOKEN + value: none_needed + - name: KEYCLOAK_TOKEN + value: + - name: ANALYSIS_ID + value: + - name: PROJECT_ID + value: + - name: DEPLOYMENT_NAME + value: + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: IfNotPresent + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + imagePullSecrets: + - name: flame-harbor-credentials + schedulerName: default-scheduler + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 +status: + observedGeneration: 1 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 + availableReplicas: 1 + conditions: + - type: Available + status: 'True' + reason: MinimumReplicasAvailable + message: Deployment has minimum availability. + - type: Progressing + status: 'True' + reason: NewReplicaSetAvailable + message: >- + ReplicaSet "" + has successfully progressed. +``` + +### Nginx Deployment +Nginx serves as a sidecar proxy, acting as the *only* means of communication between the analysis pod and everything else. The partnered analysis container can communicate only through the endpoints defined within this Nginx deployment (endpoint descriptions can be found in the [ConfigMap](#configmap) section), and like the analysis deployment, the same restrictive Network Policy is applied to the pods in this deployment through the use of specific labels and selectors. + +The created Nginx pod is only capable of communication with the partnered analysis pod, itself, and the DNS service for your kubernetes cluster. Because the analysis pod needs to communicate with other FLAME components, it must be able to discover those services within the kubernetes cluster and thus requires access to the kubernetes DNS service to resolve these service names. + +#### Template +Each Nginx deployment can be defined with the following template: +```yaml +kind: Deployment +apiVersion: apps/v1 +metadata: + name: nginx- + namespace: default + generation: 1 + labels: + app: nginx- + component: flame-analysis-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx- + template: + metadata: + labels: + app: nginx- + component: flame-analysis-nginx + spec: + volumes: + - name: nginx-vol + configMap: + name: nginx--config + items: + - key: nginx.conf + path: nginx.conf + defaultMode: 420 + containers: + - name: nginx- + image: nginx:latest + ports: + - containerPort: 80 + protocol: TCP + resources: {} + volumeMounts: + - name: nginx-vol + mountPath: /etc/nginx/nginx.conf + subPath: nginx.conf + livenessProbe: + httpGet: + path: /healthz + port: 80 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 5 + periodSeconds: 20 + successThreshold: 1 + failureThreshold: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: Always + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + schedulerName: default-scheduler + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 +status: + observedGeneration: 1 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 + availableReplicas: 1 + conditions: + - type: Available + status: 'True' + reason: MinimumReplicasAvailable + message: Deployment has minimum availability. + - type: Progressing + status: 'True' + reason: NewReplicaSetAvailable + message: >- + ReplicaSet + "nginx--" has + successfully progressed. +``` + +## Services +A kubernetes [Service](https://kubernetes.io/docs/concepts/services-networking/service/) is what allows a specific application to be exposed and accessed within a Pod. Kubernetes creates an endpoint to the specified Pod and given port, and because Pods are ephemeral, a separate Service resource is required to direct traffic to correct Pod. For the FLAME Node software, services are created for both analysis and Nginx Pods at ports `8000` and `80`, respectively. These services use the same labels and selectors as the deployments, and thus are subject the same restrictive Network Policy. + +Below are the configurations for both the analysis and Nginx Services. + +### Analysis Service Template +```yaml +kind: Service +apiVersion: v1 +metadata: + name: + namespace: default + labels: + app: + component: flame-analysis +spec: + ports: + - protocol: TCP + port: 80 + targetPort: 8000 + selector: + app: + type: ClusterIP +``` + +### Nginx Service Template +```yaml +kind: Service +apiVersion: v1 +metadata: + name: nginx- + namespace: default + labels: + app: nginx- + component: flame-analysis-nginx +spec: + ports: + - protocol: TCP + port: 80 + targetPort: 80 + selector: + app: nginx- + type: ClusterIP +``` + +## ConfigMap +A kubernetes [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) is used in the FLAME Node to define the endpoints for the Nginx sidecar pod by providing the imported Nginx configuration. Because the traffic from the analysis pod is tightly controlled, it is necessary to pre-define the Nginx endpoints with which this pod can use for communication and transmitting results. The endpoints are to enable communication with other Flame Node components and are configured such that each one will only accept connections from the analysis container (as defined by its Service IP). + +::: info Incoming Messages +One endpoint, `/analysis`, is configured to allow the FLAME Message Broker and Pod Orchestrator to send information to the analysis pod and serves as the **only** point of ingress to the analysis. +::: + +The ConfigMap resource name with use the format of `nginx--config` and is defined as such: +```yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: nginx--config + namespace: default + labels: + component: flame-nginx-analysis-config-map +data: + nginx.conf: |2- + + worker_processes 1; + events { worker_connections 1024; } + http { + sendfile on; + + server { + listen 80; + + client_max_body_size 0; + chunked_transfer_encoding on; + + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # health check + location /healthz { + return 200 'healthy'; + } + # analysis deployment to kong + location /kong { + rewrite ^/kong(/.*) $1 break; + proxy_pass http://flame-node-kong-proxy; + allow ; + deny all; + } + + location ~ ^/storage/(final|local|intermediate)/ { + rewrite ^/storage(/.*) $1 break; + proxy_pass http://flame-node-node-result-service:8080; + allow ; + deny all; + } + + location /hub-adapter/kong/datastore/ { + rewrite ^/hub-adapter(/.*) $1 break; + proxy_pass http://flame-node-hub-adapter-service:5000; + allow ; + deny all; + } + + # analysis deployment to message broker: participants + location ~ ^/message-broker/analyses//participants(|/self) { + rewrite ^/message-broker(/.*) $1 break; + proxy_pass http://flame-node-node-message-broker; + allow ; + deny all; + } + + # analysis deployment to message broker: analysis message + location ~ ^/message-broker/analyses//messages(|/subscriptions) { + rewrite ^/message-broker(/.*) $1 break; + proxy_pass http://flame-node-node-message-broker; + allow ; + deny all; + } + # analysis deployment to message broker: healthz + location /message-broker/healthz { + rewrite ^/message-broker(/.*) $1 break; + proxy_pass http://flame-node-node-message-broker; + allow ; + deny all; + } + + # analysis deployment to po log stream + location /po/stream_logs { + #rewrite ^/po(/.*) $1 break; + proxy_pass http://flame-node-po-service:8000; + allow ; + deny all; + proxy_connect_timeout 10s; + proxy_send_timeout 120s; + proxy_read_timeout 120s; + send_timeout 120s; + } + + # message-broker/pod-orchestration to analysis deployment + location /analysis { + rewrite ^/analysis(/.*) $1 break; + proxy_pass http://; + allow ; + allow ; + deny all; + } + } + } +``` + +## Network Policy +The Network Policy resource is a policy which restricts traffic either exiting (egress) or entering (ingress) a matching pod. It is applied to any pod with a matching label, in the case of the FLAME Node, the label is `app: ` meaning that any resource in the kubernetes cluster with a matching label selector will have this network policy applied to it e.g. the analysis and nginx pods. the applied policy contains rules for both ingress and egress. The ingress policy makes it so that only traffic coming from the associated Nginx pod is allowed, while the egress policy only allows requests to be sent to either the Nginx pod or the kubernetes cluster's DNS pod. + +The DNS permission is necessary to enable pod name resolution within the kubernetes cluster, thus allowing the analysis pod to communicate with the FLAME components. No other traffic or communication, including to others pods or the internet, is capable by the analysis and Nginx pods while this policy is in place. + +Here is the template describing this policy: +```yaml +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: nginx-to--policy + namespace: default + labels: + component: flame-nginx-to-analysis-policy +spec: + podSelector: + matchLabels: + app: + ingress: + - from: + - podSelector: + matchLabels: + app: nginx- + egress: + - to: + - podSelector: + matchLabels: + app: nginx- + - podSelector: + matchLabels: + k8s-app: kube-dns + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + policyTypes: + - Ingress + - Egress +``` diff --git a/src/guide/admin/index.md b/src/guide/admin/index.md index c36dde9b..87ff99a5 100644 --- a/src/guide/admin/index.md +++ b/src/guide/admin/index.md @@ -13,7 +13,7 @@ The administrator will oversee all of those actions within their realm. Administrators have the following tasks in FLAME, either in the central App or in their local node setup: -**``Hub``** +**`Hub`** - [Realm-](/guide/admin/realms), [identity provider-](/guide/admin/identity-providers), [robot-](/guide/admin/robots), [user-](/guide/admin/users) & [role-management](/guide/admin/roles) - [Viewing and assigning permissions](/guide/admin/permissions) - [Registering and managing the local node](/guide/admin/node-management) @@ -24,3 +24,5 @@ local node setup: - [Managing Data Stores](/guide/admin/data-store-management) - [Executing an analysis](/guide/admin/analysis-execution) - [Configuring Keycloak](/guide/admin/keycloak-access-control) +- [Analysis Definitions](/guide/admin/analysis-definition) +- [Bucket Setup](/guide/admin/bucket-setup-for-data-store) From b00407942da6cb147fcfe3ff1099d69d9466de73 Mon Sep 17 00:00:00 2001 From: davidhieber Date: Thu, 30 Oct 2025 13:14:37 +0100 Subject: [PATCH 2/4] docs: enhance analysis deployment documentation for clarity and detail Co-authored-by: Nightknight3000 --- src/guide/admin/analysis-definition.md | 91 +++++++++++++------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/src/guide/admin/analysis-definition.md b/src/guide/admin/analysis-definition.md index c8204174..e86ae196 100644 --- a/src/guide/admin/analysis-definition.md +++ b/src/guide/admin/analysis-definition.md @@ -1,36 +1,29 @@ # Analysis Definition in Kubernetes -As the administrator of your FLAME Node, it is important to understand how the analyses are being deployed on your system. While the [publicly available helm chart for the FLAME Node](https://github.com/PrivateAIM/helm/tree/master/charts/flame-node) makes it easy to see exactly how the components are defined, the analyses themselves are deployed using the Pod Orchestrator using the [Python kubernetes library](https://github.com/kubernetes-client/python) making it more difficult to quickly assess their configuration. This page covers the various kubernetes resources that are deployed when an analysis is started and well as how certain parameters can be modified to fit your security requirements. +As the administrator of your FLAME Node, it is important to understand how the analyses are being deployed on your system. While the [publicly available helm chart for the FLAME Node](https://github.com/PrivateAIM/helm/tree/master/charts/flame-node) makes it easy to see exactly how the components are defined, the analyses themselves are deployed using the Pod Orchestrator using the [Python Kubernetes library](https://github.com/kubernetes-client/python) making it more difficult to quickly assess their configuration. This page covers the various Kubernetes resources that are deployed when an analysis is started as well as how certain parameters can be modified to fit your security requirements. Here is a brief overview of the resources that are deployed when initiating an analysis: * [Analysis Deployment](#analysis-deployment) - * Analysis ReplicaSet - * Analysis Pod -* [Nginx Deployment](#nginx-deployment) - * Nginx ReplicaSet - * Nginx Pod + * Analysis Pod +* [NGINX Deployment](#nginx-deployment) + * NGINX Pod * [Services](#services) * [ConfigMap](#configmap) * [NetworkPolicy](#network-policy) -## Deployments -When a FLAME Analysis is started, the Pod Orchestrator service creates two separate deployments: one for the analysis itself, and one for a nginx instance. Both are required for the analysis to be able to run and transmit its results, but as shown below, both have very stringent policies in place to severely limit their traffic. - -Each [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) is so configured to create a [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) which is responsible for maintaining a specified number of [Pod](https://kubernetes.io/docs/concepts/workloads/pods/) replicas at any given time. By using deployments, the workload can be better managed, and also allow one to monitor the state of the rollout and scale the workload as needed. Additionally, this template enables the use of [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) which are subsequently used to apply a restrictive [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to the generated Pods thus controlling the traffic in and out of the analysis container. - -### Analysis Deployment -Though the code for each analysis is manually reviewed and approved prior to running on any node, precautions are still taken to lock down all traffic both entering and leaving the Pod in which it is running in the kubernetes cluster. By default, every analysis deployed by the Pod Orchestrator has a restrictive Network Policy (see [NetworkPolicy](#network-policy) below) applied to it using the labels and selectors. - -However, the analysis cannot run in complete isolation since it still requires access to the data and needs to communicate with other FLAME components for sending progress updates and the results. In order to control its communication, a Nginx sidecar container is deployed in parallel with the analysis which serves as a proxy for all requests into and exiting the container. Details on how this Nginx sidecar controls traffic is discussed in the [Nginx Deployment](#nginx-deployment) section. - -An additional security measure to ensure that the analysis pod was created using the FLAME pipeline is verification using the OIDC protocol and the included Keycloak instance. Keycloak serves as an identity provider (IDP) to check whether requests made by certain components or services are who they say they are by bundling a JSON Web Token (JWT) with their request. Our software registers the FLAME services with Keycloak upon deployment and communication is authenticated using the OAuth2 endpoints. +## Analysis Deployment +::: info Kubernetes Deployments +A [Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) is a resource which manages the creation and updating of Pods, Kubernetes resources built around Docker containers. Each Deployment is configured to create a [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) which is responsible for maintaining a specified number of [Pod](https://kubernetes.io/docs/concepts/workloads/pods/) replicas at any given time, serving as backups in case the main Pod fails due unforeseen reasons. By using Deployments, the workload can be better managed, and also allow one to monitor the state of the rollout and scale the workload as needed. Additionally, this template enables the use of [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) which are subsequently used to apply [NetworkPolicies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to the generated Pods, thus controlling the traffic in and out of the container. +::: +Though the code for each analysis is manually reviewed and approved prior to running on any node, FLAME operates under a minimal-to-none trust assumption. For an analysis this means, precautions are taken to lock down all traffic both entering and leaving the Analysis Pod in which it is running in the Kubernetes cluster. By default, every analysis deployed by the Pod Orchestrator has a restrictive Network Policy (see [NetworkPolicy](#network-policy) below) applied to it using the labels and selectors, isolating it fully from the surrounding network. -When an analysis is deployed via the FLAME UI or gateway, the Pod Orchestrator first verifies that the request came from an official FLAME component by checking the included JWT against Keycloak, and if authenticated, proceeds to register a new client within Keycloak. This registration process generates a token that is included in the analysis deployment and is subsequently used for retrieving a JWT from Keycloak that is included in all of its sent requests, including those sent for accessing the desired protected data being shared by your organization. +However, the analysis cannot run in absolute isolation since it still requires access to the data and needs to be able to communicate with other FLAME components in order to access data, send progress updates and intermediate and final results. When a FLAME Analysis is started, the Pod Orchestrator service creates two separate Deployments: one for the analysis itself, and one for a NGINX instance. The Analysis Deployment executes the analysis script, while the NGINX Deployment acts as its forward proxy. In order to not infringe on the hosting system's safety, the Analysis Deployment is subject to very stringent policies in place to severely limit its traffic, making the NGINX Deployment its single possible point of interaction (outside of Kubernetes' own kube-dns service responsible for resolving the Analysis Deployment's cluster IP address). Details on how this NGINX sidecar controls traffic is discussed in the [NGINX Deployment](#nginx-deployment) section. +An additional security measure to ensure that the Analysis Pod was created using the FLAME pipeline is verification using the OIDC protocol and the included Keycloak instance. Keycloak serves as an identity provider (IDP) to check whether requests made by certain components or services are who they say they are by bundling a JSON Web Token (JWT) with their request. Our software registers the FLAME services with Keycloak upon deployment and communication is authenticated using the OAuth2 endpoints. -#### Template -Each analysis deployment can be defined with the following template: +### Template +Each Analysis Deployment is defined following this template: ```yaml kind: Deployment apiVersion: apps/v1 @@ -106,13 +99,11 @@ status: has successfully progressed. ``` -### Nginx Deployment -Nginx serves as a sidecar proxy, acting as the *only* means of communication between the analysis pod and everything else. The partnered analysis container can communicate only through the endpoints defined within this Nginx deployment (endpoint descriptions can be found in the [ConfigMap](#configmap) section), and like the analysis deployment, the same restrictive Network Policy is applied to the pods in this deployment through the use of specific labels and selectors. - -The created Nginx pod is only capable of communication with the partnered analysis pod, itself, and the DNS service for your kubernetes cluster. Because the analysis pod needs to communicate with other FLAME components, it must be able to discover those services within the kubernetes cluster and thus requires access to the kubernetes DNS service to resolve these service names. +### NGINX Deployment +NGINX serves as a sidecar proxy, acting as the *only* means of communication between the Analysis Pod and everything else. The partnered analysis container can communicate only through the endpoints defined within this NGINX Deployment (endpoint descriptions can be found in the [ConfigMap](#configmap) section). #### Template -Each Nginx deployment can be defined with the following template: +Each NGINX Deployment can be defined with the following template: ```yaml kind: Deployment apiVersion: apps/v1 @@ -199,9 +190,12 @@ status: ``` ## Services -A kubernetes [Service](https://kubernetes.io/docs/concepts/services-networking/service/) is what allows a specific application to be exposed and accessed within a Pod. Kubernetes creates an endpoint to the specified Pod and given port, and because Pods are ephemeral, a separate Service resource is required to direct traffic to correct Pod. For the FLAME Node software, services are created for both analysis and Nginx Pods at ports `8000` and `80`, respectively. These services use the same labels and selectors as the deployments, and thus are subject the same restrictive Network Policy. +::: info Kubernetes Service +A [Kubernetes Service](https://kubernetes.io/docs/concepts/services-networking/service/) is what allows a specific application to be exposed and accessed within a Pod. Kubernetes creates an endpoint to the specified Pod and given port, and because Pods are ephemeral, a separate Service resource is required to direct traffic to correct Pod. +::: +For the FLAME Node software, services are created for both analysis and NGINX Pods at ports `8000` and `80`, respectively. These services use the same labels and selectors as the Deployments, and thus are subject the same restrictive Network Policy. -Below are the configurations for both the analysis and Nginx Services. +Below are the configurations for both the Analysis and NGINX Services. ### Analysis Service Template ```yaml @@ -223,7 +217,7 @@ spec: type: ClusterIP ``` -### Nginx Service Template +### NGINX Service Template ```yaml kind: Service apiVersion: v1 @@ -244,13 +238,13 @@ spec: ``` ## ConfigMap -A kubernetes [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) is used in the FLAME Node to define the endpoints for the Nginx sidecar pod by providing the imported Nginx configuration. Because the traffic from the analysis pod is tightly controlled, it is necessary to pre-define the Nginx endpoints with which this pod can use for communication and transmitting results. The endpoints are to enable communication with other Flame Node components and are configured such that each one will only accept connections from the analysis container (as defined by its Service IP). +A Kubernetes [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) is used in the FLAME Node to define the endpoints for the NGINX sidecar Pod by providing the imported NGINX configuration. Because the traffic from the Analysis Pod is tightly controlled, it is necessary to pre-define the NGINX endpoints which this Pod can use for communication and transmitting results. The endpoints are to enable communication with other FLAME Node components and are configured such that each one will only accept connections from the analysis container (as defined by its Service IP). ::: info Incoming Messages -One endpoint, `/analysis`, is configured to allow the FLAME Message Broker and Pod Orchestrator to send information to the analysis pod and serves as the **only** point of ingress to the analysis. +Note: One endpoint, `/analysis`, is configured to allow the FLAME Message Broker and Pod Orchestrator to send/retrieve information to/from the Analysis Pod and serves as the **only** point of ingress to the analysis. ::: -The ConfigMap resource name with use the format of `nginx--config` and is defined as such: +The ConfigMap resource name is formatted as `nginx--config` and defined as such: ```yaml kind: ConfigMap apiVersion: v1 @@ -283,7 +277,9 @@ data: location /healthz { return 200 'healthy'; } - # analysis deployment to kong + + + # egress: analysis deployment to kong location /kong { rewrite ^/kong(/.*) $1 break; proxy_pass http://flame-node-kong-proxy; @@ -291,13 +287,17 @@ data: deny all; } + + # egress: analysis deployment to result-service location ~ ^/storage/(final|local|intermediate)/ { rewrite ^/storage(/.*) $1 break; - proxy_pass http://flame-node-node-result-service:8080; + proxy_pass http://flame-node-node-result-service:8080; allow ; deny all; } + + # egress: analysis deployment to hub-adapter location /hub-adapter/kong/datastore/ { rewrite ^/hub-adapter(/.*) $1 break; proxy_pass http://flame-node-hub-adapter-service:5000; @@ -305,22 +305,22 @@ data: deny all; } - # analysis deployment to message broker: participants - location ~ ^/message-broker/analyses//participants(|/self) { + + # egress: analysis deployment to message broker: participants + location ~ ^/message-broker/analyses/}/participants(|/self) { rewrite ^/message-broker(/.*) $1 break; proxy_pass http://flame-node-node-message-broker; allow ; deny all; } - - # analysis deployment to message broker: analysis message + # egress: analysis deployment to message broker: analysis message location ~ ^/message-broker/analyses//messages(|/subscriptions) { rewrite ^/message-broker(/.*) $1 break; proxy_pass http://flame-node-node-message-broker; allow ; deny all; } - # analysis deployment to message broker: healthz + # egress: analysis deployment to message broker: healthz location /message-broker/healthz { rewrite ^/message-broker(/.*) $1 break; proxy_pass http://flame-node-node-message-broker; @@ -328,7 +328,8 @@ data: deny all; } - # analysis deployment to po log stream + + # egress: analysis deployment to po: stream logs location /po/stream_logs { #rewrite ^/po(/.*) $1 break; proxy_pass http://flame-node-po-service:8000; @@ -340,10 +341,11 @@ data: send_timeout 120s; } - # message-broker/pod-orchestration to analysis deployment + + # ingress: message-broker/pod-orchestration to analysis deployment location /analysis { rewrite ^/analysis(/.*) $1 break; - proxy_pass http://; + proxy_pass http://; allow ; allow ; deny all; @@ -353,9 +355,10 @@ data: ``` ## Network Policy -The Network Policy resource is a policy which restricts traffic either exiting (egress) or entering (ingress) a matching pod. It is applied to any pod with a matching label, in the case of the FLAME Node, the label is `app: ` meaning that any resource in the kubernetes cluster with a matching label selector will have this network policy applied to it e.g. the analysis and nginx pods. the applied policy contains rules for both ingress and egress. The ingress policy makes it so that only traffic coming from the associated Nginx pod is allowed, while the egress policy only allows requests to be sent to either the Nginx pod or the kubernetes cluster's DNS pod. - -The DNS permission is necessary to enable pod name resolution within the kubernetes cluster, thus allowing the analysis pod to communicate with the FLAME components. No other traffic or communication, including to others pods or the internet, is capable by the analysis and Nginx pods while this policy is in place. +::: info Kubernetes Network Policy +A [Kubernetes Network Policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) is a resource which restricts traffic either exiting (egress) or entering (ingress) a Pod and It is applied to any Pod via label selectors. +::: +In the case of the FLAME Node, the label to apply Network Policies onto is `app: ` meaning that any resource in the Kubernetes cluster with a matching label selector will have this network policy applied to it e.g. the Analysis Pod. The ingress policy makes it so that only traffic coming from the associated NGINX Pod is allowed, while the egress policy only allows requests to be sent to either the NGINX Pod or the Kubernetes cluster's DNS Pod (named 'kube-dns'). The DNS permission is necessary to enable Pod name resolution within the Kubernetes cluster, thus allowing the Analysis Pod to communicate with the NGINX. No other traffic or communication, including to others Pods or the internet, is capable by the Analysis Pod while this policy is in place. Here is the template describing this policy: ```yaml From 2d72b18d8956fda74da29d7fb7f2da28456fe2c6 Mon Sep 17 00:00:00 2001 From: davidhieber Date: Thu, 30 Oct 2025 13:15:12 +0100 Subject: [PATCH 3/4] docs: enhance analysis deployment documentation for clarity and detail Co-authored-by: Nightknight3000 --- src/guide/admin/analysis-definition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guide/admin/analysis-definition.md b/src/guide/admin/analysis-definition.md index e86ae196..9bc817e5 100644 --- a/src/guide/admin/analysis-definition.md +++ b/src/guide/admin/analysis-definition.md @@ -356,7 +356,7 @@ data: ## Network Policy ::: info Kubernetes Network Policy -A [Kubernetes Network Policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) is a resource which restricts traffic either exiting (egress) or entering (ingress) a Pod and It is applied to any Pod via label selectors. +A [Kubernetes Network Policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) is a resource which restricts traffic either exiting (egress) or entering (ingress) a Pod and is applied to any Pod via label selectors. ::: In the case of the FLAME Node, the label to apply Network Policies onto is `app: ` meaning that any resource in the Kubernetes cluster with a matching label selector will have this network policy applied to it e.g. the Analysis Pod. The ingress policy makes it so that only traffic coming from the associated NGINX Pod is allowed, while the egress policy only allows requests to be sent to either the NGINX Pod or the Kubernetes cluster's DNS Pod (named 'kube-dns'). The DNS permission is necessary to enable Pod name resolution within the Kubernetes cluster, thus allowing the Analysis Pod to communicate with the NGINX. No other traffic or communication, including to others Pods or the internet, is capable by the Analysis Pod while this policy is in place. From 532101cf00756fec49e708ec5235574faca4a55f Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Thu, 30 Oct 2025 13:35:48 +0100 Subject: [PATCH 4/4] style: fix header level in node analysis definition --- src/guide/admin/analysis-definition.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guide/admin/analysis-definition.md b/src/guide/admin/analysis-definition.md index 9bc817e5..7cfbad2c 100644 --- a/src/guide/admin/analysis-definition.md +++ b/src/guide/admin/analysis-definition.md @@ -99,10 +99,10 @@ status: has successfully progressed. ``` -### NGINX Deployment +## NGINX Deployment NGINX serves as a sidecar proxy, acting as the *only* means of communication between the Analysis Pod and everything else. The partnered analysis container can communicate only through the endpoints defined within this NGINX Deployment (endpoint descriptions can be found in the [ConfigMap](#configmap) section). -#### Template +### Template Each NGINX Deployment can be defined with the following template: ```yaml kind: Deployment