diff --git a/CHANGELOG.md b/CHANGELOG.md index 5425f6ac..34736ee2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [0.17.0](https://github.com/stacklok/codegate-ui/compare/v0.16.0...v0.17.0) (2025-02-20) + + +### Features + +* add workspaces impacted by provider deletion ([#340](https://github.com/stacklok/codegate-ui/issues/340)) ([5c0544f](https://github.com/stacklok/codegate-ui/commit/5c0544f57fadc742fe160ee6f359cc5da5f8337e)) +* strip markdown in messages table ([#336](https://github.com/stacklok/codegate-ui/issues/336)) ([2f8ab95](https://github.com/stacklok/codegate-ui/commit/2f8ab953590deca22271604b0400b7c5c19c40be)) +* support PII on the dashboard ([#326](https://github.com/stacklok/codegate-ui/issues/326)) ([279fe57](https://github.com/stacklok/codegate-ui/commit/279fe57f68994466c8b1f94c227dadb177e56c77)) + + +### Bug Fixes + +* audit vuln deps ([#332](https://github.com/stacklok/codegate-ui/issues/332)) ([73c55a2](https://github.com/stacklok/codegate-ui/commit/73c55a2b3cf763c7b78747836c551f41dc8dfda5)) +* inline code word wrap ([#335](https://github.com/stacklok/codegate-ui/issues/335)) ([38715de](https://github.com/stacklok/codegate-ui/commit/38715de6395b7ae0e2f50fd6ce8f64e4c341c42f)) + ## [0.16.0](https://github.com/stacklok/codegate-ui/compare/v0.15.0...v0.16.0) (2025-02-17) diff --git a/package-lock.json b/package-lock.json index 5c0268d6..fe141cf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vite-project", - "version": "0.16.0", + "version": "0.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vite-project", - "version": "0.16.0", + "version": "0.17.0", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -36,7 +36,9 @@ "react-markdown": "^9.0.1", "react-router-dom": "^7.1.1", "react-syntax-highlighter": "^15.6.1", + "remark": "^15.0.1", "remark-gfm": "^4.0.0", + "strip-markdown": "^6.0.0", "tailwind-merge": "^2.5.5", "tailwind-variants": "^0.3.1", "tailwindcss-animate": "^1.0.7", @@ -56,7 +58,7 @@ "@types/hast": "^3.0.4", "@types/node": "^22.13.1", "@types/react": "^19.0.2", - "@types/react-dom": "^19.0.2", + "@types/react-dom": "^19.0.3", "@typescript-eslint/parser": "^8.23.0", "@vitejs/plugin-react-swc": "^3.5.0", "@vitest/coverage-istanbul": "^3.0.5", @@ -70,7 +72,7 @@ "eslint-plugin-react-refresh": "^0.4.16", "eslint-plugin-tailwindcss": "3.17.5", "globals": "^15.12.0", - "hast": "^0.0.2", + "hast": "^1.0.0", "husky": "^9.1.6", "jsdom": "^25.0.1", "knip": "^5.43.6", @@ -3774,9 +3776,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz", - "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", + "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", "cpu": [ "arm" ], @@ -3788,9 +3790,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz", - "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", + "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", "cpu": [ "arm64" ], @@ -3802,9 +3804,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz", - "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", + "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", "cpu": [ "arm64" ], @@ -3815,9 +3817,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz", - "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", + "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", "cpu": [ "x64" ], @@ -3829,9 +3831,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz", - "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", + "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", "cpu": [ "arm64" ], @@ -3843,9 +3845,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz", - "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", + "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", "cpu": [ "x64" ], @@ -3857,9 +3859,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz", - "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", + "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", "cpu": [ "arm" ], @@ -3871,9 +3873,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz", - "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", + "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", "cpu": [ "arm" ], @@ -3885,9 +3887,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz", - "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", + "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", "cpu": [ "arm64" ], @@ -3899,9 +3901,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz", - "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", + "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", "cpu": [ "arm64" ], @@ -3913,9 +3915,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz", - "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", + "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", "cpu": [ "loong64" ], @@ -3927,9 +3929,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz", - "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", + "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", "cpu": [ "ppc64" ], @@ -3941,9 +3943,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz", - "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", + "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", "cpu": [ "riscv64" ], @@ -3955,9 +3957,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz", - "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", + "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", "cpu": [ "s390x" ], @@ -3969,9 +3971,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz", - "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", + "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", "cpu": [ "x64" ], @@ -3983,9 +3985,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz", - "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", + "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", "cpu": [ "x64" ], @@ -3997,9 +3999,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz", - "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", + "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", "cpu": [ "arm64" ], @@ -4011,9 +4013,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz", - "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", + "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", "cpu": [ "ia32" ], @@ -4025,9 +4027,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz", - "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", + "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", "cpu": [ "x64" ], @@ -4613,9 +4615,9 @@ } }, "node_modules/@types/react-dom": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz", - "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz", + "integrity": "sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5557,16 +5559,6 @@ "dev": true, "license": "MIT" }, - "node_modules/attach-ware": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/attach-ware/-/attach-ware-1.1.1.tgz", - "integrity": "sha512-OpavlXWZkyE7m28fpCWF/RmxCukC1edukJp9IKjEpZs/O11H3896DkLpK7lMiL8ZDx2yxo9FrZQaeHkyJGcIuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "unherit": "^1.0.0" - } - }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -5844,16 +5836,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -6201,13 +6183,6 @@ "node": ">=6" } }, - "node_modules/co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha512-CQsjCRiNObI8AtTsNIBDRMQ4oMR83CzEswHYahClvul7gKk+lDQiOKv+5qh7LQWf5sh6jkZNispz/QlsZxyNgA==", - "dev": true, - "license": "MIT" - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6632,68 +6607,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -6779,29 +6692,6 @@ "node": ">=10.13.0" } }, - "node_modules/ent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.2.tgz", - "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "punycode": "^1.4.1", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ent/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -7029,13 +6919,6 @@ "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -8195,22 +8078,12 @@ } }, "node_modules/hast": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/hast/-/hast-0.0.2.tgz", - "integrity": "sha512-1MrzC9MtAYhzLix2w++pGEtRyCm6N1fcxCjx+1xJo/92fNDRFemFaum18XWd8No3f+FgT9lv6fKOC8LZRcxxuw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast/-/hast-1.0.0.tgz", + "integrity": "sha512-vFUqlRV5C+xqP76Wwq2SrM0kipnmpxJm7OfvVXpB35Fp+Fn4MV+ozr+JZr5qFvyR1q/U+Foim2x+3P+x9S1PLA==", + "deprecated": "Renamed to rehype", "dev": true, - "license": "MIT", - "dependencies": { - "bail": "^1.0.0", - "camelcase": "^1.2.1", - "ent": "^2.2.0", - "escape-html": "^1.0.3", - "htmlparser2": "^3.8.3", - "param-case": "^1.1.1", - "property-information": "^2.0.0", - "trim": "0.0.1", - "unified": "^2.1.0" - } + "license": "MIT" }, "node_modules/hast-util-parse-selector": { "version": "2.2.5", @@ -8262,46 +8135,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast/node_modules/bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast/node_modules/property-information": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-2.0.0.tgz", - "integrity": "sha512-8oVcjnCeqANq/exCzgse3D47GBmgOuI47vNya7xBIJhUXeh49AjZuXWw2gTh1UuN4rfwz5pEv2ZFzu45vBby5A==", - "dev": true, - "license": "MIT" - }, - "node_modules/hast/node_modules/unified": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/unified/-/unified-2.1.4.tgz", - "integrity": "sha512-qa4nA26ms49OczPueTt7G46r89TOlwAJ4pEk2U4mwkV1wNhjttItF03SE/YnfkgWg14tzmAHXGhJp2GhDYwn1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "attach-ware": "^1.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "unherit": "^1.0.4", - "vfile": "^1.0.0", - "ware": "^1.3.0" - } - }, - "node_modules/hast/node_modules/vfile": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-1.4.0.tgz", - "integrity": "sha512-7Fz639rwERslMqQCuf1/0H4Tqe2q484Xl6X/jsKqrP7IjFcDODFURhv0GekMnImpbj9pTOojtqL7r39LJJkjGA==", - "dev": true, - "license": "MIT" - }, "node_modules/hastscript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", @@ -8419,28 +8252,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -8555,13 +8366,6 @@ "node": ">=8" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/inline-style-parser": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", @@ -9700,13 +9504,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true, - "license": "MIT" - }, "node_modules/lowlight": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", @@ -11319,16 +11116,6 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, - "node_modules/param-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-1.1.2.tgz", - "integrity": "sha512-gksk6zeZQxwBm1AHsKh+XDFsTGf1LvdZSkkpSIkfDtzW+EQj/P2PBgNb3Cs0Y9Xxqmbciv2JZe3fWU6Xbher+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "sentence-case": "^1.1.2" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -11543,9 +11330,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "funding": [ { "type": "opencollective", @@ -11562,7 +11349,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -12305,21 +12092,6 @@ "pify": "^2.3.0" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -12512,6 +12284,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-gfm": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", @@ -12694,9 +12481,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", - "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", + "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12710,42 +12497,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.1", - "@rollup/rollup-android-arm64": "4.29.1", - "@rollup/rollup-darwin-arm64": "4.29.1", - "@rollup/rollup-darwin-x64": "4.29.1", - "@rollup/rollup-freebsd-arm64": "4.29.1", - "@rollup/rollup-freebsd-x64": "4.29.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", - "@rollup/rollup-linux-arm-musleabihf": "4.29.1", - "@rollup/rollup-linux-arm64-gnu": "4.29.1", - "@rollup/rollup-linux-arm64-musl": "4.29.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", - "@rollup/rollup-linux-riscv64-gnu": "4.29.1", - "@rollup/rollup-linux-s390x-gnu": "4.29.1", - "@rollup/rollup-linux-x64-gnu": "4.29.1", - "@rollup/rollup-linux-x64-musl": "4.29.1", - "@rollup/rollup-win32-arm64-msvc": "4.29.1", - "@rollup/rollup-win32-ia32-msvc": "4.29.1", - "@rollup/rollup-win32-x64-msvc": "4.29.1", + "@rollup/rollup-android-arm-eabi": "4.34.8", + "@rollup/rollup-android-arm64": "4.34.8", + "@rollup/rollup-darwin-arm64": "4.34.8", + "@rollup/rollup-darwin-x64": "4.34.8", + "@rollup/rollup-freebsd-arm64": "4.34.8", + "@rollup/rollup-freebsd-x64": "4.34.8", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", + "@rollup/rollup-linux-arm-musleabihf": "4.34.8", + "@rollup/rollup-linux-arm64-gnu": "4.34.8", + "@rollup/rollup-linux-arm64-musl": "4.34.8", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", + "@rollup/rollup-linux-riscv64-gnu": "4.34.8", + "@rollup/rollup-linux-s390x-gnu": "4.34.8", + "@rollup/rollup-linux-x64-gnu": "4.34.8", + "@rollup/rollup-linux-x64-musl": "4.34.8", + "@rollup/rollup-win32-arm64-msvc": "4.34.8", + "@rollup/rollup-win32-ia32-msvc": "4.34.8", + "@rollup/rollup-win32-x64-msvc": "4.34.8", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", - "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -12796,27 +12569,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -12888,16 +12640,6 @@ "semver": "bin/semver.js" } }, - "node_modules/sentence-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-1.1.3.tgz", - "integrity": "sha512-laa/UDTPXsrQnoN/Kc8ZO7gTeEjMsuPiDgUCk9N0iINRZvqAMCTXjGl8+tD27op1eF/JHbdUlEUmovDh6AX7sA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^1.1.1" - } - }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -13216,16 +12958,6 @@ "dev": true, "license": "MIT" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -13464,6 +13196,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-markdown": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-markdown/-/strip-markdown-6.0.0.tgz", + "integrity": "sha512-mSa8FtUoX3ExJYDkjPUTC14xaBAn4Ik5GPQD45G5E2egAmeV3kHgVSTfIoSDggbF6Pk9stahVgqsLCNExv6jHw==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/style-to-object": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", @@ -13911,13 +13655,6 @@ "node": ">=18" } }, - "node_modules/trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "deprecated": "Use String.prototype.trim() instead", - "dev": true - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -14241,21 +13978,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -14505,15 +14227,15 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -14848,16 +14570,6 @@ "node": ">=18" } }, - "node_modules/ware": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", - "integrity": "sha512-Y2HUDMktriUm+SR2gZWxlrszcgtXExlhQYZ8QJNYbl22jum00KIUcHJ/h/sdAXhWTJcbSkiMYN9Z2tWbWYSrrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "wrap-fn": "^0.1.0" - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -15152,16 +14864,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-fn": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", - "integrity": "sha512-xDLdGx0M8JQw9QDAC9s5NUxtg9MI09F6Vbxa2LYoSoCvzJnx2n81YMIfykmXEGsUvuLaxnblJTzhSOjUOX37ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "co": "3.1.0" - } - }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", diff --git a/package.json b/package.json index 9d8cac23..4478ea30 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vite-project", "private": true, - "version": "0.16.0", + "version": "0.17.0", "type": "module", "scripts": { "dev": "vite", @@ -49,7 +49,9 @@ "react-markdown": "^9.0.1", "react-router-dom": "^7.1.1", "react-syntax-highlighter": "^15.6.1", + "remark": "^15.0.1", "remark-gfm": "^4.0.0", + "strip-markdown": "^6.0.0", "tailwind-merge": "^2.5.5", "tailwind-variants": "^0.3.1", "tailwindcss-animate": "^1.0.7", @@ -69,7 +71,7 @@ "@types/hast": "^3.0.4", "@types/node": "^22.13.1", "@types/react": "^19.0.2", - "@types/react-dom": "^19.0.2", + "@types/react-dom": "^19.0.3", "@typescript-eslint/parser": "^8.23.0", "@vitejs/plugin-react-swc": "^3.5.0", "@vitest/coverage-istanbul": "^3.0.5", @@ -83,7 +85,7 @@ "eslint-plugin-react-refresh": "^0.4.16", "eslint-plugin-tailwindcss": "3.17.5", "globals": "^15.12.0", - "hast": "^0.0.2", + "hast": "^1.0.0", "husky": "^9.1.6", "jsdom": "^25.0.1", "knip": "^5.43.6", diff --git a/src/api/generated/@tanstack/react-query.gen.ts b/src/api/generated/@tanstack/react-query.gen.ts index 102ed855..a22a7421 100644 --- a/src/api/generated/@tanstack/react-query.gen.ts +++ b/src/api/generated/@tanstack/react-query.gen.ts @@ -28,6 +28,7 @@ import { v1DeleteWorkspaceCustomInstructions, v1GetWorkspaceMuxes, v1SetWorkspaceMuxes, + v1ListWorkspacesByProvider, v1StreamSse, v1VersionCheck, v1GetWorkspaceTokenUsage, @@ -76,6 +77,7 @@ import type { V1SetWorkspaceMuxesData, V1SetWorkspaceMuxesError, V1SetWorkspaceMuxesResponse, + V1ListWorkspacesByProviderData, V1GetWorkspaceTokenUsageData, } from '../types.gen' @@ -687,6 +689,27 @@ export const v1SetWorkspaceMuxesMutation = ( return mutationOptions } +export const v1ListWorkspacesByProviderQueryKey = ( + options: OptionsLegacyParser +) => [createQueryKey('v1ListWorkspacesByProvider', options)] + +export const v1ListWorkspacesByProviderOptions = ( + options: OptionsLegacyParser +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await v1ListWorkspacesByProvider({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }) + return data + }, + queryKey: v1ListWorkspacesByProviderQueryKey(options), + }) +} + export const v1StreamSseQueryKey = (options?: OptionsLegacyParser) => [ createQueryKey('v1StreamSse', options), ] diff --git a/src/api/generated/sdk.gen.ts b/src/api/generated/sdk.gen.ts index 9834d09b..e9d216d9 100644 --- a/src/api/generated/sdk.gen.ts +++ b/src/api/generated/sdk.gen.ts @@ -73,6 +73,9 @@ import type { V1SetWorkspaceMuxesData, V1SetWorkspaceMuxesError, V1SetWorkspaceMuxesResponse, + V1ListWorkspacesByProviderData, + V1ListWorkspacesByProviderError, + V1ListWorkspacesByProviderResponse, V1StreamSseError, V1StreamSseResponse, V1VersionCheckError, @@ -512,6 +515,25 @@ export const v1SetWorkspaceMuxes = ( }) } +/** + * List Workspaces By Provider + * List workspaces by provider ID. + */ +export const v1ListWorkspacesByProvider = < + ThrowOnError extends boolean = false, +>( + options: OptionsLegacyParser +) => { + return (options?.client ?? client).get< + V1ListWorkspacesByProviderResponse, + V1ListWorkspacesByProviderError, + ThrowOnError + >({ + ...options, + url: '/api/v1/workspaces/{provider_id}', + }) +} + /** * Stream Sse * Send alerts event diff --git a/src/api/generated/types.gen.ts b/src/api/generated/types.gen.ts index 5f2dc9be..50634d20 100644 --- a/src/api/generated/types.gen.ts +++ b/src/api/generated/types.gen.ts @@ -35,11 +35,11 @@ export type Alert = { | { [key: string]: unknown } - | null; - trigger_type: string; - trigger_category: AlertSeverity; - timestamp: string; -}; + | null + trigger_type: string + trigger_category: AlertSeverity + timestamp: string +} /** * Represents an alert with it's respective conversation. @@ -60,8 +60,8 @@ export type AlertConversation = { } export enum AlertSeverity { - INFO = "info", - CRITICAL = "critical", + INFO = 'info', + CRITICAL = 'critical', } /** @@ -111,6 +111,7 @@ export type Conversation = { export type CreateOrRenameWorkspaceRequest = { name: string + config?: WorkspaceConfig | null rename_to?: string | null } @@ -145,15 +146,16 @@ export type ModelByProvider = { * Represents the different types of matchers we support. */ export enum MuxMatcherType { - CATCH_ALL = "catch_all", - FILENAME_MATCH = "filename_match", - REQUEST_TYPE_MATCH = "request_type_match", + CATCH_ALL = 'catch_all', + FILENAME_MATCH = 'filename_match', + REQUEST_TYPE_MATCH = 'request_type_match', } /** * Represents a mux rule for a provider. */ export type MuxRule = { + provider_name?: string | null provider_id: string model: string matcher_type: MuxMatcherType @@ -251,6 +253,20 @@ export type Workspace = { is_active: boolean } +export type WorkspaceConfig = { + system_prompt: string + muxing_rules: Array +} + +/** + * Returns a workspace ID with model name + */ +export type WorkspaceWithModel = { + id: string + name: string + provider_model_name: string +} + export type HealthCheckHealthGetResponse = unknown export type HealthCheckHealthGetError = unknown @@ -462,6 +478,16 @@ export type V1SetWorkspaceMuxesResponse = void export type V1SetWorkspaceMuxesError = HTTPValidationError +export type V1ListWorkspacesByProviderData = { + path: { + provider_id: string + } +} + +export type V1ListWorkspacesByProviderResponse = Array + +export type V1ListWorkspacesByProviderError = HTTPValidationError + export type V1StreamSseResponse = unknown export type V1StreamSseError = unknown diff --git a/src/api/openapi.json b/src/api/openapi.json index cde65b55..a6d16753 100644 --- a/src/api/openapi.json +++ b/src/api/openapi.json @@ -989,6 +989,55 @@ } } }, + "/api/v1/workspaces/{provider_id}": { + "get": { + "tags": [ + "CodeGate API", + "Workspaces" + ], + "summary": "List Workspaces By Provider", + "description": "List workspaces by provider ID.", + "operationId": "v1_list_workspaces_by_provider", + "parameters": [ + { + "name": "provider_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Provider Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WorkspaceWithModel" + }, + "title": "Response V1 List Workspaces By Provider" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/api/v1/alerts_notification": { "get": { "tags": [ @@ -1478,6 +1527,16 @@ "type": "string", "title": "Name" }, + "config": { + "anyOf": [ + { + "$ref": "#/components/schemas/WorkspaceConfig" + }, + { + "type": "null" + } + ] + }, "rename_to": { "anyOf": [ { @@ -1590,6 +1649,17 @@ }, "MuxRule": { "properties": { + "provider_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider Name" + }, "provider_id": { "type": "string", "title": "Provider Id" @@ -1842,6 +1912,52 @@ "is_active" ], "title": "Workspace" + }, + "WorkspaceConfig": { + "properties": { + "system_prompt": { + "type": "string", + "title": "System Prompt" + }, + "muxing_rules": { + "items": { + "$ref": "#/components/schemas/MuxRule" + }, + "type": "array", + "title": "Muxing Rules" + } + }, + "type": "object", + "required": [ + "system_prompt", + "muxing_rules" + ], + "title": "WorkspaceConfig" + }, + "WorkspaceWithModel": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "name": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "title": "Name" + }, + "provider_model_name": { + "type": "string", + "title": "Provider Model Name" + } + }, + "type": "object", + "required": [ + "id", + "name", + "provider_model_name" + ], + "title": "WorkspaceWithModel", + "description": "Returns a workspace ID with model name" } } } diff --git a/src/components/Markdown.tsx b/src/components/Markdown.tsx index e183a01e..279e960a 100644 --- a/src/components/Markdown.tsx +++ b/src/components/Markdown.tsx @@ -86,6 +86,9 @@ const CodeInline = ({ language={language} codeTagProps={{ className: 'px-1 py-0.5 bg-gray-200 rounded-sm border border-gray-400', + style: { + whiteSpace: 'unset', + }, }} useInlineStyles={false} PreTag="span" diff --git a/src/constants/empty-state-strings.ts b/src/constants/empty-state-strings.ts index 58b54a56..1b1572d4 100644 --- a/src/constants/empty-state-strings.ts +++ b/src/constants/empty-state-strings.ts @@ -7,6 +7,8 @@ export const emptyStateStrings = { anErrorOccurred: 'An error occurred', noLeakedSecretsDetected: 'No leaked secrets detected', noMaliciousPackagesDetected: 'No malicious packages detected', + noPIIDetected: + 'No leaked personally identifiable information (PII) detected', noSearchResultsFor: (x: string | undefined): string => !x ? 'No search results' : `No search results for "${x}"`, }, @@ -22,6 +24,8 @@ export const emptyStateStrings = { 'Messages are issues that CodeGate has detected and mitigated in your interactions with the LLM.', secretsDesc: 'CodeGate helps you protect sensitive information from being accidentally exposed to AI models and third-party AI provider systems by redacting detected secrets from your prompts using encryption.', + piiDesc: + 'CodeGate helps you protect sensitive personally identifiable information (PII) from being accidentally exposed to AI models and third-party AI provider systems by redacting detected PII from your prompts using encryption.', maliciousDesc: "CodeGate's dependency risk insight helps protect your codebase from malicious or vulnerable dependencies. It identifies potentially risky packages and suggests fixed versions or alternative packages to consider.", }, diff --git a/src/features/dashboard-messages/components/__tests__/table-messages.alerts.test.tsx b/src/features/dashboard-messages/components/__tests__/table-messages.alerts.test.tsx index 1d12083a..ab7d0462 100644 --- a/src/features/dashboard-messages/components/__tests__/table-messages.alerts.test.tsx +++ b/src/features/dashboard-messages/components/__tests__/table-messages.alerts.test.tsx @@ -33,6 +33,11 @@ it('shows zero in alerts counts when no alerts', async () => { name: /secrets count/i, }) ).toHaveTextContent('0') + expect( + screen.getByRole('button', { + name: /personally identifiable information.*count/i, + }) + ).toHaveTextContent('0') }) it('shows count of malicious alerts in row', async () => { @@ -80,3 +85,26 @@ it('shows count of secret alerts in row', async () => { }) ).toHaveTextContent('10') }) + +it('shows count of pii alerts in row', async () => { + server.use( + http.get(mswEndpoint('/api/v1/workspaces/:workspace_name/messages'), () => + HttpResponse.json([ + mockConversation({ + alertsConfig: { numAlerts: 10, type: 'pii' }, + }), + ]) + ) + ) + render() + + await waitFor(() => { + expect(screen.queryByText(/loading.../i)).not.toBeInTheDocument() + }) + + expect( + screen.getByRole('button', { + name: /pii/i, + }) + ).toHaveTextContent('10') +}) diff --git a/src/features/dashboard-messages/components/__tests__/table-messages.empty-state.test.tsx b/src/features/dashboard-messages/components/__tests__/table-messages.empty-state.test.tsx index 1d38805c..556232f5 100644 --- a/src/features/dashboard-messages/components/__tests__/table-messages.empty-state.test.tsx +++ b/src/features/dashboard-messages/components/__tests__/table-messages.empty-state.test.tsx @@ -304,6 +304,48 @@ const TEST_CASES: TestCase[] = [ actions: null, }, }, + { + testDescription: 'Has alerts, view is "pii"', + handlers: [ + http.get(mswEndpoint('/api/v1/workspaces'), () => { + return HttpResponse.json({ + workspaces: [ + { + name: 'default', + is_active: true, + }, + { + name: 'foo-bar', + is_active: false, + }, + ], + }) + }), + http.get(mswEndpoint('/api/v1/workspaces/archive'), () => { + return HttpResponse.json({ + workspaces: [], + }) + }), + http.get( + mswEndpoint('/api/v1/workspaces/:workspace_name/messages'), + () => { + return HttpResponse.json( + Array.from({ length: 10 }).map(() => mockAlert({ type: 'pii' })) + ) + } + ), + ], + searchParams: { + view: AlertsFilterView.PII, + search: null, + }, + expected: { + title: emptyStateStrings.title.noPIIDetected, + body: emptyStateStrings.body.piiDesc, + illustrationTestId: IllustrationTestId.DONE, + actions: null, + }, + }, ] test.each(TEST_CASES)('$testDescription', async (testCase) => { diff --git a/src/features/dashboard-messages/components/__tests__/tabs-messages.test.tsx b/src/features/dashboard-messages/components/__tests__/tabs-messages.test.tsx index 4c83f9ad..f4a0bd53 100644 --- a/src/features/dashboard-messages/components/__tests__/tabs-messages.test.tsx +++ b/src/features/dashboard-messages/components/__tests__/tabs-messages.test.tsx @@ -40,56 +40,42 @@ test('shows correct count of all packages', async () => { }) }) -test('shows correct count of malicious packages', async () => { - server.use( - http.get(mswEndpoint('/api/v1/workspaces/:workspace_name/messages'), () => { - return HttpResponse.json( - Array.from({ length: 13 }).map(() => - mockConversation({ - alertsConfig: { - type: 'malicious', - numAlerts: 1, - }, - }) - ) +const filteredCases = [ + { tabLabel: /malicious/i, alertType: 'malicious' as const, count: 13 }, + { tabLabel: /secrets/i, alertType: 'secret' as const, count: 10 }, + { tabLabel: /pii/i, alertType: 'pii' as const, count: 9 }, +] + +filteredCases.forEach(({ tabLabel, alertType, count }) => { + test(`shows correct count of ${alertType} packages`, async () => { + server.use( + http.get( + mswEndpoint('/api/v1/workspaces/:workspace_name/messages'), + () => { + return HttpResponse.json( + Array.from({ length: count }).map(() => + mockConversation({ + alertsConfig: { + type: alertType, + numAlerts: 1, + }, + }) + ) + ) + } ) - }) - ) + ) - const { getByRole } = render( - -
foo
-
- ) + const { getByRole } = render( + +
foo
+
+ ) - await waitFor(() => { - expect(getByRole('tab', { name: /malicious/i })).toHaveTextContent('13') - }) -}) - -test('shows correct count of secret packages', async () => { - server.use( - http.get(mswEndpoint('/api/v1/workspaces/:workspace_name/messages'), () => { - return HttpResponse.json( - Array.from({ length: 13 }).map(() => - mockConversation({ - alertsConfig: { - type: 'secret', - numAlerts: 1, - }, - }) - ) + await waitFor(() => { + expect(getByRole('tab', { name: tabLabel })).toHaveTextContent( + String(count) ) }) - ) - - const { getByRole } = render( - -
foo
-
- ) - - await waitFor(() => { - expect(getByRole('tab', { name: /secrets/i })).toHaveTextContent('13') }) }) diff --git a/src/features/dashboard-messages/components/conversation-summary.tsx b/src/features/dashboard-messages/components/conversation-summary.tsx index 549a9e03..bb60f0ea 100644 --- a/src/features/dashboard-messages/components/conversation-summary.tsx +++ b/src/features/dashboard-messages/components/conversation-summary.tsx @@ -12,6 +12,7 @@ import { Hash01, Key01, PackageX, + Passport, Server05, } from '@untitled-ui/icons-react' @@ -51,8 +52,8 @@ function AlertsSummaryCount({ }: { count: number type: { - singular: 'malicious package' | 'secret' - plural: 'malicious packages' | 'secrets' + singular: string + plural: string } }) { const typeText = count === 1 ? type.singular : type.plural @@ -97,9 +98,9 @@ export function ConversationSummary({ }: { conversation: Conversation }) { - const { malicious, secrets } = conversation.alerts + const { malicious, secrets, pii } = conversation.alerts ? countConversationAlerts(conversation.alerts) - : { malicious: 0, secrets: 0 } + : { malicious: 0, secrets: 0, pii: 0 } return (
@@ -166,6 +167,19 @@ export function ConversationSummary({ /> } /> + + } + />
) diff --git a/src/features/dashboard-messages/components/table-messages-empty-state.tsx b/src/features/dashboard-messages/components/table-messages-empty-state.tsx index cc378f72..8a109a80 100644 --- a/src/features/dashboard-messages/components/table-messages-empty-state.tsx +++ b/src/features/dashboard-messages/components/table-messages-empty-state.tsx @@ -120,6 +120,17 @@ function EmptyStateSecrets() { ) } +function EmptyStatePII() { + return ( + + ) +} + export function EmptyStateError() { return ( ) + .with( + { + hasWorkspaceMessages: true, + hasMultipleWorkspaces: P.any, + view: AlertsFilterView.PII, + isLoading: false, + }, + () => + ) .with( { hasWorkspaceMessages: true, diff --git a/src/features/dashboard-messages/components/table-messages.tsx b/src/features/dashboard-messages/components/table-messages.tsx index d082251a..3dd2ac25 100644 --- a/src/features/dashboard-messages/components/table-messages.tsx +++ b/src/features/dashboard-messages/components/table-messages.tsx @@ -11,12 +11,14 @@ import { TooltipTrigger, } from '@stacklok/ui-kit' import { Alert, Conversation, QuestionType } from '@/api/generated' +import { remark } from 'remark' +import strip from 'strip-markdown' import { useClientSidePagination } from '@/hooks/useClientSidePagination' import { TableAlertTokenUsage } from './table-alert-token-usage' import { useMessagesFilterSearchParams } from '../hooks/use-messages-filter-search-params' -import { Key01, PackageX } from '@untitled-ui/icons-react' +import { Key01, PackageX, Passport } from '@untitled-ui/icons-react' import { EmptyStateError, TableMessagesEmptyState, @@ -31,11 +33,14 @@ import { TableMessagesColumn, } from '../constants/table-messages-columns' import { formatTime } from '@/lib/format-time' +import { isAlertPii } from '@/lib/is-alert-pii' const getPromptText = (conversation: Conversation) => { - return (conversation.question_answers[0]?.question?.message ?? 'N/A') - .trim() - .slice(0, 200) // arbitrary slice to prevent long prompts + const markdownSource = + conversation.question_answers[0]?.question?.message ?? 'N/A' + const fullText = remark().use(strip).processSync(markdownSource) + + return fullText.toString().trim().slice(0, 200) // arbitrary slice to prevent long prompts } function getTypeText(type: QuestionType) { @@ -52,10 +57,12 @@ function getTypeText(type: QuestionType) { function countAlerts(alerts: Alert[]): { secrets: number malicious: number + pii: number } { return { secrets: alerts.filter(isAlertSecret).length, malicious: alerts.filter(isAlertMalicious).length, + pii: alerts.filter(isAlertPii).length, } } @@ -93,7 +100,7 @@ function AlertsSummaryCount({ } function AlertsSummaryCellContent({ alerts }: { alerts: Alert[] }) { - const { malicious, secrets } = countAlerts(alerts) + const { malicious, secrets, pii } = countAlerts(alerts) return (
@@ -113,6 +120,14 @@ function AlertsSummaryCellContent({ alerts }: { alerts: Alert[] }) { count={secrets} icon={Key01} /> +
) } diff --git a/src/features/dashboard-messages/components/tabs-messages.tsx b/src/features/dashboard-messages/components/tabs-messages.tsx index 8b163b18..52ac99a3 100644 --- a/src/features/dashboard-messages/components/tabs-messages.tsx +++ b/src/features/dashboard-messages/components/tabs-messages.tsx @@ -18,11 +18,13 @@ import { import { SearchFieldMessages } from './search-field-messages' import { tv } from 'tailwind-variants' import { useQueryGetWorkspaceMessages } from '@/hooks/use-query-get-workspace-messages' +import { isConversationWithPII } from '@/lib/is-alert-pii' type AlertsCount = { all: number malicious: number secrets: number + pii: number } function select(data: V1GetWorkspaceMessagesResponse): AlertsCount { @@ -36,10 +38,13 @@ function select(data: V1GetWorkspaceMessagesResponse): AlertsCount { isConversationWithSecretAlerts, ]).length + const pii: number = multiFilter(data, [isConversationWithPII]).length + return { all, malicious, secrets, + pii, } } @@ -103,6 +108,7 @@ export function TabsMessages({ children }: { children: React.ReactNode }) { count={data?.secrets ?? 0} id={AlertsFilterView.SECRETS} /> + diff --git a/src/features/dashboard-messages/hooks/use-messages-filter-search-params.ts b/src/features/dashboard-messages/hooks/use-messages-filter-search-params.ts index 4144a9ff..a311d16e 100644 --- a/src/features/dashboard-messages/hooks/use-messages-filter-search-params.ts +++ b/src/features/dashboard-messages/hooks/use-messages-filter-search-params.ts @@ -6,6 +6,7 @@ export enum AlertsFilterView { ALL = 'all', MALICIOUS = 'malicious', SECRETS = 'secrets', + PII = 'pii', } const alertsFilterSchema = z.object({ diff --git a/src/features/dashboard-messages/hooks/use-query-get-workspace-messages-table.ts b/src/features/dashboard-messages/hooks/use-query-get-workspace-messages-table.ts index fc9a3c5f..f82b9b6f 100644 --- a/src/features/dashboard-messages/hooks/use-query-get-workspace-messages-table.ts +++ b/src/features/dashboard-messages/hooks/use-query-get-workspace-messages-table.ts @@ -9,6 +9,7 @@ import { isConversationWithMaliciousAlerts } from '../../../lib/is-alert-malicio import { isConversationWithSecretAlerts } from '../../../lib/is-alert-secret' import { filterMessagesBySubstring } from '../lib/filter-messages-by-substring' import { useQueryGetWorkspaceMessages } from '@/hooks/use-query-get-workspace-messages' +import { isConversationWithPII } from '@/lib/is-alert-pii' const FILTER: Record< AlertsFilterView, @@ -17,6 +18,7 @@ const FILTER: Record< all: () => true, malicious: isConversationWithMaliciousAlerts, secrets: isConversationWithSecretAlerts, + pii: isConversationWithPII, } export function useQueryGetWorkspaceMessagesTable() { diff --git a/src/features/dashboard-messages/lib/count-conversation-alerts.ts b/src/features/dashboard-messages/lib/count-conversation-alerts.ts index 9e88253d..13931bed 100644 --- a/src/features/dashboard-messages/lib/count-conversation-alerts.ts +++ b/src/features/dashboard-messages/lib/count-conversation-alerts.ts @@ -1,13 +1,16 @@ import { Alert } from '@/api/generated' import { isAlertMalicious } from '@/lib/is-alert-malicious' +import { isAlertPii } from '@/lib/is-alert-pii' import { isAlertSecret } from '@/lib/is-alert-secret' export function countConversationAlerts(alerts: Alert[]): { secrets: number malicious: number + pii: number } { return { secrets: alerts.filter(isAlertSecret).length, malicious: alerts.filter(isAlertMalicious).length, + pii: alerts.filter(isAlertPii).length, } } diff --git a/src/features/providers/components/table-providers.tsx b/src/features/providers/components/table-providers.tsx index a24bea52..d10dfab4 100644 --- a/src/features/providers/components/table-providers.tsx +++ b/src/features/providers/components/table-providers.tsx @@ -51,12 +51,12 @@ const COLUMNS: Column[] = [ function CellRenderer({ column, row, - deleteProvider, }: { column: Column row: ProviderEndpoint - deleteProvider: () => void }) { + const deleteProvider = useConfirmDeleteProvider(row.id) + return match(column.id) .with(COLUMN_MAP.provider, () => ( <> @@ -90,7 +90,15 @@ function CellRenderer({ )) .with(COLUMN_MAP.configuration, () => ( - )) @@ -99,7 +107,6 @@ function CellRenderer({ export function TableProviders() { const { data: providers = [] } = useProviders() - const deleteProvider = useConfirmDeleteProvider() return ( @@ -117,15 +124,7 @@ export function TableProviders() { id={column.id} alignment={column.alignment} > - { - deleteProvider({ - path: { provider_id: row.id as string }, - }) - }} - /> + )} diff --git a/src/features/providers/components/workspaces-by-provider.tsx b/src/features/providers/components/workspaces-by-provider.tsx new file mode 100644 index 00000000..63a35df0 --- /dev/null +++ b/src/features/providers/components/workspaces-by-provider.tsx @@ -0,0 +1,25 @@ +import { V1ListWorkspacesByProviderResponse } from '@/api/generated' +import { Badge } from '@stacklok/ui-kit' +import { uniqBy } from 'lodash' + +export function WorkspacesByProvider({ + workspaces = [], +}: { + workspaces: V1ListWorkspacesByProviderResponse | undefined +}) { + if (workspaces.length === 0) return null + return ( +
+

The following workspaces will be impacted by this action

+
+ {uniqBy(workspaces, 'name').map((item, index) => { + return ( + + {item.name} + + ) + })} +
+
+ ) +} diff --git a/src/features/providers/hooks/use-confirm-delete-provider.tsx b/src/features/providers/hooks/use-confirm-delete-provider.tsx index 3cce4bd6..24b23623 100644 --- a/src/features/providers/hooks/use-confirm-delete-provider.tsx +++ b/src/features/providers/hooks/use-confirm-delete-provider.tsx @@ -1,19 +1,22 @@ import { useConfirm } from '@/hooks/use-confirm' import { useCallback } from 'react' import { useMutationDeleteProvider } from './use-mutation-delete-provider' +import { useQueryWorkspacesByProvider } from './use-query-workspaces-by-provider' +import { WorkspacesByProvider } from '../components/workspaces-by-provider' -export function useConfirmDeleteProvider() { +export function useConfirmDeleteProvider( + providerId: string | undefined | null +) { const { mutateAsync: deleteProvider } = useMutationDeleteProvider() - + const { data: workspaces } = useQueryWorkspacesByProvider(providerId) const { confirm } = useConfirm() return useCallback( async (...params: Parameters) => { const answer = await confirm( <> -

- Are you sure you want to permanently delete this provider? -

+ +

Are you sure you want to permanently delete this provider?

, { buttons: { @@ -28,6 +31,6 @@ export function useConfirmDeleteProvider() { return deleteProvider(...params) } }, - [confirm, deleteProvider] + [confirm, deleteProvider, workspaces] ) } diff --git a/src/features/providers/hooks/use-invalidate-providers-queries.ts b/src/features/providers/hooks/use-invalidate-providers-queries.ts index 3c147681..d18dc080 100644 --- a/src/features/providers/hooks/use-invalidate-providers-queries.ts +++ b/src/features/providers/hooks/use-invalidate-providers-queries.ts @@ -1,6 +1,7 @@ import { v1ListAllModelsForAllProvidersQueryKey, v1ListProviderEndpointsQueryKey, + v1ListWorkspacesByProviderQueryKey, } from '@/api/generated/@tanstack/react-query.gen' import { useQueryClient } from '@tanstack/react-query' import { useCallback } from 'react' @@ -13,6 +14,7 @@ export function useInvalidateProvidersQueries() { invalidateQueries(queryClient, [ v1ListProviderEndpointsQueryKey, v1ListAllModelsForAllProvidersQueryKey, + v1ListWorkspacesByProviderQueryKey, ]) }, [queryClient]) diff --git a/src/features/providers/hooks/use-query-workspaces-by-provider.ts b/src/features/providers/hooks/use-query-workspaces-by-provider.ts new file mode 100644 index 00000000..ef3484a1 --- /dev/null +++ b/src/features/providers/hooks/use-query-workspaces-by-provider.ts @@ -0,0 +1,16 @@ +import { v1ListWorkspacesByProviderOptions } from '@/api/generated/@tanstack/react-query.gen' +import { useQuery } from '@tanstack/react-query' + +export function useQueryWorkspacesByProvider( + providerId: string | undefined | null +) { + if (!providerId) { + throw new Error('providerId is required') + } + + return useQuery({ + ...v1ListWorkspacesByProviderOptions({ path: { provider_id: providerId } }), + // eslint-disable-next-line no-restricted-syntax + refetchOnMount: true, + }) +} diff --git a/src/features/workspace/hooks/use-invalidate-workspace-queries.ts b/src/features/workspace/hooks/use-invalidate-workspace-queries.ts index 277db5b4..58957dc6 100644 --- a/src/features/workspace/hooks/use-invalidate-workspace-queries.ts +++ b/src/features/workspace/hooks/use-invalidate-workspace-queries.ts @@ -1,5 +1,7 @@ import { + v1GetWorkspaceMuxesQueryKey, v1ListArchivedWorkspacesQueryKey, + v1ListWorkspacesByProviderQueryKey, v1ListWorkspacesQueryKey, } from '@/api/generated/@tanstack/react-query.gen' import { invalidateQueries } from '@/lib/react-query-utils' @@ -13,6 +15,8 @@ export function useInvalidateWorkspaceQueries() { invalidateQueries(queryClient, [ v1ListWorkspacesQueryKey, v1ListArchivedWorkspacesQueryKey, + v1GetWorkspaceMuxesQueryKey, + v1ListWorkspacesByProviderQueryKey, ]) }, [queryClient]) diff --git a/src/lib/is-alert-pii.ts b/src/lib/is-alert-pii.ts new file mode 100644 index 00000000..aa1d5ea9 --- /dev/null +++ b/src/lib/is-alert-pii.ts @@ -0,0 +1,14 @@ +import { Alert, AlertConversation, Conversation } from '@/api/generated' + +export function isConversationWithPII( + conversation: Conversation | null +): boolean { + return conversation?.alerts?.some(isAlertPii) ?? false +} + +export function isAlertPii(alert: Alert | AlertConversation | null) { + return ( + alert?.trigger_category === 'critical' && + alert.trigger_type === 'codegate-pii' + ) +} diff --git a/src/mocks/msw/mockers/alert.mock.ts b/src/mocks/msw/mockers/alert.mock.ts index e8a4e262..91768414 100644 --- a/src/mocks/msw/mockers/alert.mock.ts +++ b/src/mocks/msw/mockers/alert.mock.ts @@ -1,11 +1,16 @@ -import { Alert, AlertSeverity } from "@/api/generated"; -import { faker } from "@faker-js/faker"; +import { Alert, AlertSeverity } from '@/api/generated' +import { faker } from '@faker-js/faker' const ALERT_SECRET_FIELDS = { trigger_string: 'foo', trigger_type: 'codegate-secrets', } satisfies Pick +const ALERT_PII_FIELDS = { + trigger_string: 'fakemail@fakedomain.mock', + trigger_type: 'codegate-pii', +} satisfies Pick + const ALERT_MALICIOUS_FIELDS = { trigger_string: { name: 'invokehttp', @@ -31,7 +36,7 @@ const getBaseAlert = ({ export const mockAlert = ({ type, }: { - type: 'secret' | 'malicious' + type: 'secret' | 'malicious' | 'pii' }): Alert => { const timestamp = faker.date.recent().toISOString() @@ -54,6 +59,14 @@ export const mockAlert = ({ ...ALERT_SECRET_FIELDS, } + return result + } + case 'pii': { + const result: Alert = { + ...base, + ...ALERT_PII_FIELDS, + } + return result } } diff --git a/src/mocks/msw/mockers/conversation.mock.ts b/src/mocks/msw/mockers/conversation.mock.ts index 11c10862..88879b08 100644 --- a/src/mocks/msw/mockers/conversation.mock.ts +++ b/src/mocks/msw/mockers/conversation.mock.ts @@ -12,7 +12,7 @@ export function mockConversation({ withTokenUsage?: boolean alertsConfig?: { numAlerts?: number - type?: 'secret' | 'malicious' | 'any' + type?: 'secret' | 'malicious' | 'any' | 'pii' } } = {}) { const timestamp = faker.date.recent().toISOString()