From 9db9b0f6b3d97154192032e7df4eb58337c65173 Mon Sep 17 00:00:00 2001 From: Javier Feliz Date: Sun, 3 Aug 2025 00:23:06 -0400 Subject: [PATCH] Got claude started on the docs. Will have to update them heavily --- .gitignore | 1 + bun.lock | 603 +++++++++++++++++++++++++++++++++ docs/.vitepress/config.mjs | 89 +++++ docs/TESTING_KEYS.md | 171 ---------- docs/config/email.md | 360 ++++++++++++++++++++ docs/config/environment.md | 402 ++++++++++++++++++++++ docs/guide/applications.md | 188 ++++++++++ docs/guide/first-setup.md | 202 +++++++++++ docs/guide/installation.md | 259 ++++++++++++++ docs/guide/quick-start.md | 159 +++++++++ docs/index.md | 75 ++++ docs/integrations/grafana.md | 322 ++++++++++++++++++ docs/integrations/nextcloud.md | 370 ++++++++++++++++++++ docs/integrations/overview.md | 324 ++++++++++++++++++ docs/package.json | 10 + package.json | 2 +- 16 files changed, 3365 insertions(+), 172 deletions(-) create mode 100644 bun.lock create mode 100644 docs/.vitepress/config.mjs delete mode 100644 docs/TESTING_KEYS.md create mode 100644 docs/config/email.md create mode 100644 docs/config/environment.md create mode 100644 docs/guide/applications.md create mode 100644 docs/guide/first-setup.md create mode 100644 docs/guide/installation.md create mode 100644 docs/guide/quick-start.md create mode 100644 docs/index.md create mode 100644 docs/integrations/grafana.md create mode 100644 docs/integrations/nextcloud.md create mode 100644 docs/integrations/overview.md create mode 100644 docs/package.json diff --git a/.gitignore b/.gitignore index 32832f8..a04192a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ yarn-error.log **/caddy frankenphp frankenphp-worker.php +/docs/.vitepress/cache diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..10490cd --- /dev/null +++ b/bun.lock @@ -0,0 +1,603 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "dependencies": { + "@tailwindcss/vite": "^4.0.7", + "autoprefixer": "^10.4.20", + "axios": "^1.7.4", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^1.0", + "tailwindcss": "^4.0.7", + "vite": "^6.0", + }, + "devDependencies": { + "vitepress": "^1.6.3", + }, + "optionalDependencies": { + "@rollup/rollup-linux-x64-gnu": "4.9.5", + "@tailwindcss/oxide-linux-x64-gnu": "^4.0.1", + "lightningcss-linux-x64-gnu": "^1.29.1", + }, + }, + }, + "packages": { + "@algolia/abtesting": ["@algolia/abtesting@1.1.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-sEyWjw28a/9iluA37KLGu8vjxEIlb60uxznfTUmXImy7H5NvbpSO6yYgmgH5KiD7j+zTUUihiST0jEP12IoXow=="], + + "@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.7", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", "@algolia/autocomplete-shared": "1.17.7" } }, "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q=="], + + "@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A=="], + + "@algolia/autocomplete-preset-algolia": ["@algolia/autocomplete-preset-algolia@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA=="], + + "@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.17.7", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg=="], + + "@algolia/client-abtesting": ["@algolia/client-abtesting@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-uUdHxbfHdoppDVflCHMxRlj49/IllPwwQ2cQ8DLC4LXr3kY96AHBpW0dMyi6ygkn2MtFCc6BxXCzr668ZRhLBQ=="], + + "@algolia/client-analytics": ["@algolia/client-analytics@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-SunAgwa9CamLcRCPnPHx1V2uxdQwJGqb1crYrRWktWUdld0+B2KyakNEeVn5lln4VyeNtW17Ia7V7qBWyM/Skw=="], + + "@algolia/client-common": ["@algolia/client-common@5.35.0", "", {}, "sha512-ipE0IuvHu/bg7TjT2s+187kz/E3h5ssfTtjpg1LbWMgxlgiaZIgTTbyynM7NfpSJSKsgQvCQxWjGUO51WSCu7w=="], + + "@algolia/client-insights": ["@algolia/client-insights@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-UNbCXcBpqtzUucxExwTSfAe8gknAJ485NfPN6o1ziHm6nnxx97piIbcBQ3edw823Tej2Wxu1C0xBY06KgeZ7gA=="], + + "@algolia/client-personalization": ["@algolia/client-personalization@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-/KWjttZ6UCStt4QnWoDAJ12cKlQ+fkpMtyPmBgSS2WThJQdSV/4UWcqCUqGH7YLbwlj3JjNirCu3Y7uRTClxvA=="], + + "@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-8oCuJCFf/71IYyvQQC+iu4kgViTODbXDk3m7yMctEncRSRV+u2RtDVlpGGfPlJQOrAY7OONwJlSHkmbbm2Kp/w=="], + + "@algolia/client-search": ["@algolia/client-search@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-FfmdHTrXhIduWyyuko1YTcGLuicVbhUyRjO3HbXE4aP655yKZgdTIfMhZ/V5VY9bHuxv/fGEh3Od1Lvv2ODNTg=="], + + "@algolia/ingestion": ["@algolia/ingestion@1.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-gPzACem9IL1Co8mM1LKMhzn1aSJmp+Vp434An4C0OBY4uEJRcqsLN3uLBlY+bYvFg8C8ImwM9YRiKczJXRk0XA=="], + + "@algolia/monitoring": ["@algolia/monitoring@1.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-w9MGFLB6ashI8BGcQoVt7iLgDIJNCn4OIu0Q0giE3M2ItNrssvb8C0xuwJQyTy1OFZnemG0EB1OvXhIHOvQwWw=="], + + "@algolia/recommend": ["@algolia/recommend@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-AhrVgaaXAb8Ue0u2nuRWwugt0dL5UmRgS9LXe0Hhz493a8KFeZVUE56RGIV3hAa6tHzmAV7eIoqcWTQvxzlJeQ=="], + + "@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0" } }, "sha512-diY415KLJZ6x1Kbwl9u96Jsz0OstE3asjXtJ9pmk1d+5gPuQ5jQyEsgC+WmEXzlec3iuVszm8AzNYYaqw6B+Zw=="], + + "@algolia/requester-fetch": ["@algolia/requester-fetch@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0" } }, "sha512-uydqnSmpAjrgo8bqhE9N1wgcB98psTRRQXcjc4izwMB7yRl9C8uuAQ/5YqRj04U0mMQ+fdu2fcNF6m9+Z1BzDQ=="], + + "@algolia/requester-node-http": ["@algolia/requester-node-http@5.35.0", "", { "dependencies": { "@algolia/client-common": "5.35.0" } }, "sha512-RgLX78ojYOrThJHrIiPzT4HW3yfQa0D7K+MQ81rhxqaNyNBu4F1r+72LNHYH/Z+y9I1Mrjrd/c/Ue5zfDgAEjQ=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@babel/parser": ["@babel/parser@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.0" }, "bin": "./bin/babel-parser.js" }, "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g=="], + + "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + + "@docsearch/css": ["@docsearch/css@3.8.2", "", {}, "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ=="], + + "@docsearch/js": ["@docsearch/js@3.8.2", "", { "dependencies": { "@docsearch/react": "3.8.2", "preact": "^10.0.0" } }, "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ=="], + + "@docsearch/react": ["@docsearch/react@3.8.2", "", { "dependencies": { "@algolia/autocomplete-core": "1.17.7", "@algolia/autocomplete-preset-algolia": "1.17.7", "@docsearch/css": "3.8.2", "algoliasearch": "^5.14.2" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", "react": ">= 16.8.0 < 19.0.0", "react-dom": ">= 16.8.0 < 19.0.0", "search-insights": ">= 1 < 3" }, "optionalPeers": ["@types/react", "react", "react-dom", "search-insights"] }, "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.0", "", { "os": "android", "cpu": "arm" }, "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.0", "", { "os": "android", "cpu": "arm64" }, "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.0", "", { "os": "android", "cpu": "x64" }, "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.0", "", { "os": "linux", "cpu": "x64" }, "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.0", "", { "os": "none", "cpu": "arm64" }, "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.0", "", { "os": "none", "cpu": "x64" }, "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="], + + "@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.45", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-POOz+NjYQDy2fy1u+sIZi05N6r6oSooIGBaBcZLh7w8QOmLgJAZ6mBt+7Messp7ku9ucRua61if33BPoOZCwRQ=="], + + "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.8", "", { "os": "android", "cpu": "arm" }, "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.8", "", { "os": "android", "cpu": "arm64" }, "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.9.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.8", "", { "os": "win32", "cpu": "x64" }, "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g=="], + + "@shikijs/core": ["@shikijs/core@2.5.0", "", { "dependencies": { "@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.4" } }, "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^3.1.0" } }, "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw=="], + + "@shikijs/langs": ["@shikijs/langs@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w=="], + + "@shikijs/themes": ["@shikijs/themes@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw=="], + + "@shikijs/transformers": ["@shikijs/transformers@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/types": "2.5.0" } }, "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg=="], + + "@shikijs/types": ["@shikijs/types@2.5.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.0.8", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "tailwindcss": "4.0.8" } }, "sha512-FKArQpbrbwv08TNT0k7ejYXpF+R8knZFAatNc0acOxbgeqLzwb86r+P3LGOjIeI3Idqe9CVkZrh4GlsJLJKkkw=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.0.8", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.0.8", "@tailwindcss/oxide-darwin-arm64": "4.0.8", "@tailwindcss/oxide-darwin-x64": "4.0.8", "@tailwindcss/oxide-freebsd-x64": "4.0.8", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.8", "@tailwindcss/oxide-linux-arm64-gnu": "4.0.8", "@tailwindcss/oxide-linux-arm64-musl": "4.0.8", "@tailwindcss/oxide-linux-x64-gnu": "4.0.8", "@tailwindcss/oxide-linux-x64-musl": "4.0.8", "@tailwindcss/oxide-win32-arm64-msvc": "4.0.8", "@tailwindcss/oxide-win32-x64-msvc": "4.0.8" } }, "sha512-KfMcuAu/Iw+DcV1e8twrFyr2yN8/ZDC/odIGta4wuuJOGkrkHZbvJvRNIbQNhGh7erZTYV6Ie0IeD6WC9Y8Hcw=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.0.8", "", { "os": "android", "cpu": "arm64" }, "sha512-We7K79+Sm4mwJHk26Yzu/GAj7C7myemm7PeXvpgMxyxO70SSFSL3uCcqFbz9JA5M5UPkrl7N9fkBe/Y0iazqpA=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.0.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Lv9Isi2EwkCTG1sRHNDi0uRNN1UGFdEThUAGFrydRmQZnraGLMjN8gahzg2FFnOizDl7LB2TykLUuiw833DSNg=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.0.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-fWfywfYIlSWtKoqWTjukTHLWV3ARaBRjXCC2Eo0l6KVpaqGY4c2y8snUjp1xpxUtpqwMvCvFWFaleMoz1Vhzlw=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.0.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SO+dyvjJV9G94bnmq2288Ke0BIdvrbSbvtPLaQdqjqHR83v5L2fWADyFO+1oecHo9Owsk8MxcXh1agGVPIKIqw=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.0.8", "", { "os": "linux", "cpu": "arm" }, "sha512-ZSHggWiEblQNV69V0qUK5vuAtHP+I+S2eGrKGJ5lPgwgJeAd6GjLsVBN+Mqn2SPVfYM3BOpS9jX/zVg9RWQVDQ=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.0.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-xWpr6M0OZLDNsr7+bQz+3X7zcnDJZJ1N9gtBWCtfhkEtDjjxYEp+Lr5L5nc/yXlL4MyCHnn0uonGVXy3fhxaVA=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.0.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-5tz2IL7LN58ssGEq7h/staD7pu/izF/KeMWdlJ86WDe2Ah46LF3ET6ZGKTr5eZMrnEA0M9cVFuSPprKRHNgjeg=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.0.8", "", { "os": "linux", "cpu": "x64" }, "sha512-KSzMkhyrxAQyY2o194NKVKU9j/c+NFSoMvnHWFaNHKi3P1lb+Vq1UC19tLHrmxSkKapcMMu69D7+G1+FVGNDXQ=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.0.8", "", { "os": "linux", "cpu": "x64" }, "sha512-yFYKG5UtHTRimjtqxUWXBgI4Tc6NJe3USjRIVdlTczpLRxq/SFwgzGl5JbatCxgSRDPBFwRrNPxq+ukfQFGdrw=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.0.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-tndGujmCSba85cRCnQzXgpA2jx5gXimyspsUYae5jlPyLRG0RjXbDshFKOheVXU4TLflo7FSG8EHCBJ0EHTKdQ=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.0.8", "", { "os": "win32", "cpu": "x64" }, "sha512-T77jroAc0p4EHVVgTUiNeFn6Nj3jtD3IeNId2X+0k+N1XxfNipy81BEkYErpKLiOkNhpNFjPee8/ZVas29b2OQ=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.0.8", "", { "dependencies": { "@tailwindcss/node": "4.0.8", "@tailwindcss/oxide": "4.0.8", "lightningcss": "^1.29.1", "tailwindcss": "4.0.8" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-+SAq44yLzYlzyrb7QTcFCdU8Xa7FOA0jp+Xby7fPMUie+MY9HhJysM7Vp+vL8qIp8ceQJfLD+FjgJuJ4lL6nyg=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="], + + "@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="], + + "@vue/compiler-core": ["@vue/compiler-core@3.5.18", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/shared": "3.5.18", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.18", "", { "dependencies": { "@vue/compiler-core": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A=="], + + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.18", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/compiler-core": "3.5.18", "@vue/compiler-dom": "3.5.18", "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA=="], + + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.18", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g=="], + + "@vue/devtools-api": ["@vue/devtools-api@7.7.7", "", { "dependencies": { "@vue/devtools-kit": "^7.7.7" } }, "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg=="], + + "@vue/devtools-kit": ["@vue/devtools-kit@7.7.7", "", { "dependencies": { "@vue/devtools-shared": "^7.7.7", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA=="], + + "@vue/devtools-shared": ["@vue/devtools-shared@7.7.7", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw=="], + + "@vue/reactivity": ["@vue/reactivity@3.5.18", "", { "dependencies": { "@vue/shared": "3.5.18" } }, "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg=="], + + "@vue/runtime-core": ["@vue/runtime-core@3.5.18", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w=="], + + "@vue/runtime-dom": ["@vue/runtime-dom@3.5.18", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/runtime-core": "3.5.18", "@vue/shared": "3.5.18", "csstype": "^3.1.3" } }, "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw=="], + + "@vue/server-renderer": ["@vue/server-renderer@3.5.18", "", { "dependencies": { "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "vue": "3.5.18" } }, "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA=="], + + "@vue/shared": ["@vue/shared@3.5.18", "", {}, "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA=="], + + "@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="], + + "@vueuse/integrations": ["@vueuse/integrations@12.8.2", "", { "dependencies": { "@vueuse/core": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "fuse.js", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g=="], + + "@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="], + + "@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="], + + "algoliasearch": ["algoliasearch@5.35.0", "", { "dependencies": { "@algolia/abtesting": "1.1.0", "@algolia/client-abtesting": "5.35.0", "@algolia/client-analytics": "5.35.0", "@algolia/client-common": "5.35.0", "@algolia/client-insights": "5.35.0", "@algolia/client-personalization": "5.35.0", "@algolia/client-query-suggestions": "5.35.0", "@algolia/client-search": "5.35.0", "@algolia/ingestion": "1.35.0", "@algolia/monitoring": "1.35.0", "@algolia/recommend": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", "@algolia/requester-fetch": "5.35.0", "@algolia/requester-node-http": "5.35.0" } }, "sha512-Y+moNhsqgLmvJdgTsO4GZNgsaDWv8AOGAaPeIeHKlDn/XunoAqYbA+XNpBd1dW8GOXAUDyxC9Rxc7AV4kpFcIg=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "autoprefixer": ["autoprefixer@10.4.20", "", { "dependencies": { "browserslist": "^4.23.3", "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": "bin/autoprefixer" }, "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g=="], + + "axios": ["axios@1.7.9", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw=="], + + "birpc": ["birpc@2.5.0", "", {}, "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="], + + "browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": "cli.js" }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001700", "", {}, "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "concurrently": ["concurrently@9.1.2", "", { "dependencies": { "chalk": "^4.1.2", "lodash": "^4.17.21", "rxjs": "^7.8.1", "shell-quote": "^1.8.1", "supports-color": "^8.1.1", "tree-kill": "^1.2.2", "yargs": "^17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ=="], + + "copy-anything": ["copy-anything@3.0.5", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-libc": ["detect-libc@1.0.3", "", { "bin": "bin/detect-libc.js" }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.103", "", {}, "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="], + + "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": "bin/esbuild" }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "focus-trap": ["focus-trap@7.6.5", "", { "dependencies": { "tabbable": "^6.2.0" } }, "sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg=="], + + "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + + "form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + + "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "jiti": ["jiti@2.4.2", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + + "laravel-vite-plugin": ["laravel-vite-plugin@1.2.0", "", { "dependencies": { "picocolors": "^1.0.0", "vite-plugin-full-reload": "^1.1.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0" }, "bin": { "clean-orphaned-assets": "bin/clean.js" } }, "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ=="], + + "lightningcss": ["lightningcss@1.29.1", "", { "dependencies": { "detect-libc": "^1.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.1", "lightningcss-darwin-x64": "1.29.1", "lightningcss-freebsd-x64": "1.29.1", "lightningcss-linux-arm-gnueabihf": "1.29.1", "lightningcss-linux-arm64-gnu": "1.29.1", "lightningcss-linux-arm64-musl": "1.29.1", "lightningcss-linux-x64-gnu": "1.29.1", "lightningcss-linux-x64-musl": "1.29.1", "lightningcss-win32-arm64-msvc": "1.29.1", "lightningcss-win32-x64-msvc": "1.29.1" } }, "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.29.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.29.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.29.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.29.1", "", { "os": "linux", "cpu": "arm" }, "sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.29.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.29.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.29.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.29.1", "", { "os": "linux", "cpu": "x64" }, "sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.29.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.1", "", { "os": "win32", "cpu": "x64" }, "sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "mark.js": ["mark.js@8.11.1", "", {}, "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "minisearch": ["minisearch@7.1.2", "", {}, "sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA=="], + + "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], + + "nanoid": ["nanoid@3.3.8", "", { "bin": "bin/nanoid.cjs" }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], + + "oniguruma-to-es": ["oniguruma-to-es@3.1.1", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "preact": ["preact@10.27.0", "", {}, "sha512-/DTYoB6mwwgPytiqQTh/7SFRL98ZdiD8Sk8zIUVOxtwq4oWcwrcd1uno9fE/zZmUaUrFNYzbH14CPebOz9tZQw=="], + + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="], + + "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rollup": ["rollup@4.34.8", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@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" }, "bin": "dist/bin/rollup" }, "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ=="], + + "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], + + "search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="], + + "shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="], + + "shiki": ["shiki@2.5.0", "", { "dependencies": { "@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" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], + + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], + + "tailwindcss": ["tailwindcss@4.0.8", "", {}, "sha512-Me7N5CKR+D2A1xdWA5t5+kjjT7bwnxZOE6/yDI/ixJdJokszsn2n++mdU5yJwrsTpqFX2B9ZNMBJDwcqk9C9lw=="], + + "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], + + "tree-kill": ["tree-kill@1.2.2", "", { "bin": "cli.js" }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "vite": ["vite@6.2.0", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ=="], + + "vite-plugin-full-reload": ["vite-plugin-full-reload@1.2.0", "", { "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" } }, "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA=="], + + "vitepress": ["vitepress@1.6.3", "", { "dependencies": { "@docsearch/css": "3.8.2", "@docsearch/js": "3.8.2", "@iconify-json/simple-icons": "^1.2.21", "@shikijs/core": "^2.1.0", "@shikijs/transformers": "^2.1.0", "@shikijs/types": "^2.1.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^5.2.1", "@vue/devtools-api": "^7.7.0", "@vue/shared": "^3.5.13", "@vueuse/core": "^12.4.0", "@vueuse/integrations": "^12.4.0", "focus-trap": "^7.6.4", "mark.js": "8.11.1", "minisearch": "^7.1.1", "shiki": "^2.1.0", "vite": "^5.4.14", "vue": "^3.5.13" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-fCkfdOk8yRZT8GD9BFqusW3+GggWYZ/rYncOfmgcDtP3ualNHCAg+Robxp2/6xfH1WwPHtGpPwv7mbA3qomtBw=="], + + "vue": ["vue@3.5.18", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/compiler-sfc": "3.5.18", "@vue/runtime-dom": "3.5.18", "@vue/server-renderer": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@vue/compiler-sfc/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "rollup/@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA=="], + + "vitepress/vite": ["vite@5.4.19", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA=="], + + "@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "vitepress/vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "vitepress/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "vitepress/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "vitepress/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "vitepress/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "vitepress/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "vitepress/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "vitepress/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "vitepress/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "vitepress/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "vitepress/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "vitepress/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "vitepress/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "vitepress/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "vitepress/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "vitepress/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "vitepress/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "vitepress/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "vitepress/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "vitepress/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "vitepress/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "vitepress/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "vitepress/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "vitepress/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + } +} diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs new file mode 100644 index 0000000..b25a562 --- /dev/null +++ b/docs/.vitepress/config.mjs @@ -0,0 +1,89 @@ +import { defineConfig } from 'vitepress' + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + title: "AuthentiKate", + description: "A lightweight SSO/OIDC solution built for homelabbers", + head: [ + ['meta', { name: 'theme-color', content: '#3b82f6' }], + ], + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + logo: '/logo.svg', + + nav: [ + { text: 'Home', link: '/' }, + { text: 'Guide', link: '/guide/installation' }, + { text: 'Configuration', link: '/config/environment' }, + { text: 'Integrations', link: '/integrations/overview' } + ], + + sidebar: { + '/guide/': [ + { + text: 'Getting Started', + items: [ + { text: 'Installation', link: '/guide/installation' }, + { text: 'Quick Start', link: '/guide/quick-start' }, + { text: 'First Setup', link: '/guide/first-setup' } + ] + }, + { + text: 'User Management', + items: [ + { text: 'Creating Users', link: '/guide/users' }, + { text: 'Invitations', link: '/guide/invitations' }, + { text: 'User Profiles', link: '/guide/profiles' } + ] + }, + { + text: 'Applications', + items: [ + { text: 'Managing Apps', link: '/guide/applications' }, + { text: 'OAuth Configuration', link: '/guide/oauth' } + ] + } + ], + '/config/': [ + { + text: 'Configuration', + items: [ + { text: 'Environment Variables', link: '/config/environment' }, + { text: 'Database Setup', link: '/config/database' }, + { text: 'Security Settings', link: '/config/security' }, + { text: 'Email Configuration', link: '/config/email' } + ] + } + ], + '/integrations/': [ + { + text: 'Integrations', + items: [ + { text: 'Overview', link: '/integrations/overview' }, + { text: 'Grafana', link: '/integrations/grafana' }, + { text: 'Nextcloud', link: '/integrations/nextcloud' }, + { text: 'Traefik', link: '/integrations/traefik' }, + { text: 'Other Applications', link: '/integrations/generic' } + ] + } + ] + }, + + socialLinks: [ + { icon: 'github', link: 'https://github.com/jdubpark/authentikate' } + ], + + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2024-present AuthentiKate' + }, + + editLink: { + pattern: 'https://github.com/jdubpark/authentikate/edit/main/docs/:path' + }, + + search: { + provider: 'local' + } + } +}) diff --git a/docs/TESTING_KEYS.md b/docs/TESTING_KEYS.md deleted file mode 100644 index 9f4e12d..0000000 --- a/docs/TESTING_KEYS.md +++ /dev/null @@ -1,171 +0,0 @@ -# Testing RSA Keys Management - -This document explains how RSA keys are managed during testing to ensure that running tests doesn't interfere with production keys. - -## Overview - -The application uses RSA keys for OIDC (OpenID Connect) JWT token signing. To prevent tests from deleting or overwriting production keys, we've implemented a separate key management system for testing environments. - -## Key Features - -### 1. Environment-Aware Key Paths - -- **Production**: `storage/oauth/` -- **Testing**: `storage/testing/oauth/` - -### 2. Enhanced Generate Keys Command - -The `app:generate-keys` command now supports: - -```bash -# Generate keys in default location (environment-dependent) -php artisan app:generate-keys - -# Generate keys in custom location -php artisan app:generate-keys --path=/custom/path -``` - -**Environment Behavior:** -- Production: Uses `storage/oauth/` -- Testing: Uses `storage/testing/oauth/` - -### 3. Test Key Management Trait - -The `ManagesTestKeys` trait provides methods for managing test keys: - -```php -// Set up test keys before test suite -ManagesTestKeys::setUpTestKeys() - -// Clean up test keys after test suite -ManagesTestKeys::tearDownTestKeys() - -// Ensure test keys exist for current test -$this->ensureTestKeysExist() -``` - -### 4. CI/CD Script - -The `scripts/setup-test-keys.sh` script provides commands for CI/CD environments: - -```bash -# Set up test keys -./scripts/setup-test-keys.sh setup - -# Clean up test keys -./scripts/setup-test-keys.sh cleanup - -# Reset (cleanup and regenerate) test keys -./scripts/setup-test-keys.sh reset -``` - -## Implementation Details - -### Files Modified - -1. **`app/Console/Commands/GenerateKeys.php`** - - Added `--path` option - - Environment-aware default paths - - Uses `storage/testing/oauth/` in testing environment - -2. **`app/Http/Controllers/OIDCController.php`** - - Added helper methods `getPrivateKeyPath()` and `getPublicKeyPath()` - - Uses test keys in testing environment - -3. **`tests/Feature/GenerateKeysCommandTest.php`** - - Updated to use test directory - - Added test for custom path option - -4. **`tests/Feature/OIDCControllerTest.php`** - - Uses `ManagesTestKeys` trait - - Automatically generates test keys before tests - -5. **`.gitignore`** - - Added `/storage/testing/*` to ignore test files - -### Test Key Management - -#### Automatic Generation - -Test keys are automatically generated when needed: - -1. When running `OIDCControllerTest`, keys are generated in `beforeEach` -2. Keys are only generated if they don't already exist -3. Uses the same RSA 2048-bit specification as production - -#### Cleanup - -Test keys are cleaned up: - -1. After each test in `GenerateKeysCommandTest` -2. Can be manually cleaned using the script -3. Not committed to version control (ignored in `.gitignore`) - -## GitHub Actions Integration - -Example workflow configuration: - -```yaml -- name: Set up test RSA keys - run: ./scripts/setup-test-keys.sh setup - -- name: Run tests - run: php artisan test --coverage - -- name: Clean up test RSA keys - run: ./scripts/setup-test-keys.sh cleanup - if: always() -``` - -## Benefits - -1. **Safety**: Production keys are never affected by tests -2. **Isolation**: Each test environment has its own keys -3. **Consistency**: Same key generation process for all environments -4. **CI/CD Ready**: Works seamlessly in automated environments -5. **Flexibility**: Custom paths supported for advanced use cases - -## Usage Examples - -### Local Development - -```bash -# Run tests (keys automatically managed) -php artisan test - -# Manually generate test keys -php artisan app:generate-keys --path=storage/testing/oauth -``` - -### CI/CD Environment - -```bash -# Set up environment -./scripts/setup-test-keys.sh setup - -# Run tests -php artisan test - -# Clean up -./scripts/setup-test-keys.sh cleanup -``` - -### Custom Testing Setup - -```php -// In a test file -use Tests\Support\ManagesTestKeys; - -uses(ManagesTestKeys::class); - -beforeEach(function () { - $this->ensureTestKeysExist(); -}); -``` - -## Security Considerations - -1. Test keys are generated with the same security parameters as production -2. Test keys are temporary and not persisted -3. Test directories are excluded from version control -4. No hardcoded keys in test files \ No newline at end of file diff --git a/docs/config/email.md b/docs/config/email.md new file mode 100644 index 0000000..c09ce0f --- /dev/null +++ b/docs/config/email.md @@ -0,0 +1,360 @@ +# Email Configuration + +Email is essential for user invitations, password resets, and account verification. This guide covers how to configure email in AuthentiKate. + +## Why Email Matters + +Email is used for: +- **User Invitations**: Send registration links to new users +- **Password Resets**: Allow users to reset forgotten passwords +- **Email Verification**: Verify user email addresses +- **Account Notifications**: Security alerts and updates + +## Basic SMTP Configuration + +Set these environment variables for SMTP email: + +```bash +MAIL_MAILER=smtp +MAIL_HOST=your-smtp-server.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@domain.com +MAIL_PASSWORD=your-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +## Provider-Specific Configurations + +### Gmail + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@gmail.com +MAIL_PASSWORD=your-app-password # Not your regular Gmail password! +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=your-email@gmail.com +MAIL_FROM_NAME="Your Name" +``` + +**Important**: Use an [App Password](https://support.google.com/accounts/answer/185833), not your regular Gmail password. + +#### Creating Gmail App Password +1. Enable 2-Factor Authentication on your Google account +2. Go to **Google Account** → **Security** → **App passwords** +3. Generate a new app password for "Mail" +4. Use this 16-character password in `MAIL_PASSWORD` + +### Outlook/Hotmail + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp-mail.outlook.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@outlook.com +MAIL_PASSWORD=your-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=your-email@outlook.com +MAIL_FROM_NAME="Your Name" +``` + +### Custom Domain Email + +If you have your own domain with email hosting: + +```bash +MAIL_MAILER=smtp +MAIL_HOST=mail.yourdomain.com +MAIL_PORT=587 +MAIL_USERNAME=auth@yourdomain.com +MAIL_PASSWORD=your-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +## Email Service Providers + +### SendGrid + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.sendgrid.net +MAIL_PORT=587 +MAIL_USERNAME=apikey +MAIL_PASSWORD=your-sendgrid-api-key +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +### Mailgun + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailgun.org +MAIL_PORT=587 +MAIL_USERNAME=your-mailgun-username +MAIL_PASSWORD=your-mailgun-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +### Amazon SES + +```bash +MAIL_MAILER=smtp +MAIL_HOST=email-smtp.us-east-1.amazonaws.com # Change region as needed +MAIL_PORT=587 +MAIL_USERNAME=your-ses-smtp-username +MAIL_PASSWORD=your-ses-smtp-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +### Postmark + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.postmarkapp.com +MAIL_PORT=587 +MAIL_USERNAME=your-postmark-token +MAIL_PASSWORD=your-postmark-token +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +## Docker Compose Configuration + +### Environment Variables + +```yaml +services: + authentikate: + image: authentikate/authentikate:latest + environment: + # Gmail example + MAIL_MAILER: smtp + MAIL_HOST: smtp.gmail.com + MAIL_PORT: 587 + MAIL_USERNAME: your-email@gmail.com + MAIL_PASSWORD: your-app-password + MAIL_ENCRYPTION: tls + MAIL_FROM_ADDRESS: your-email@gmail.com + MAIL_FROM_NAME: "AuthentiKate" +``` + +### Environment File + +Create a `.env` file: + +```bash +# Email configuration +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@gmail.com +MAIL_PASSWORD=your-app-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=your-email@gmail.com +MAIL_FROM_NAME="AuthentiKate" +``` + +Reference it in docker-compose.yml: + +```yaml +services: + authentikate: + image: authentikate/authentikate:latest + env_file: .env +``` + +## Testing Email Configuration + +### Send Test Email + +AuthentiKate includes a command to test email sending: + +```bash +# Test email configuration +docker exec -it authentikate php artisan tinker + +# In the tinker console: +Mail::raw('Test email from AuthentiKate', function($message) { + $message->to('test@example.com')->subject('Test Email'); +}); +``` + +### Check Logs + +If emails aren't sending, check the logs: + +```bash +# View container logs +docker logs authentikate + +# Look for email-related errors +docker logs authentikate 2>&1 | grep -i mail +``` + +## Advanced Configuration + +### Custom SMTP Port + +Some providers use different ports: + +```bash +# Standard ports +MAIL_PORT=25 # Unencrypted (not recommended) +MAIL_PORT=587 # STARTTLS (recommended) +MAIL_PORT=465 # SSL/TLS + +# Custom port +MAIL_PORT=2525 # Some providers use alternate ports +``` + +### SSL/TLS Configuration + +```bash +# Use TLS (recommended) +MAIL_ENCRYPTION=tls + +# Use SSL (older, but still secure) +MAIL_ENCRYPTION=ssl + +# No encryption (not recommended) +MAIL_ENCRYPTION=null +``` + +### Multiple From Addresses + +Configure different senders for different email types: + +```bash +# Default sender +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" + +# Admin notifications (configure in application) +ADMIN_EMAIL_FROM=admin@yourdomain.com +ADMIN_EMAIL_NAME="AuthentiKate Admin" +``` + +## Email Templates + +AuthentiKate uses customizable email templates for different purposes: + +### Invitation Email +- **Subject**: "You're invited to join AuthentiKate" +- **Content**: Welcome message with registration link +- **Action**: "Complete Registration" button + +### Password Reset +- **Subject**: "Reset your AuthentiKate password" +- **Content**: Instructions for password reset +- **Action**: "Reset Password" button + +### Email Verification +- **Subject**: "Verify your email address" +- **Content**: Verification instructions +- **Action**: "Verify Email" button + +## Troubleshooting + +### Common Issues + +#### "Connection could not be established" +``` +Swift_TransportException: Connection could not be established +``` + +**Solutions**: +- Check SMTP server address and port +- Verify firewall isn't blocking SMTP ports +- Try different encryption settings (TLS vs SSL) + +#### "Authentication failed" +``` +Swift_TransportException: Expected response code 235 but got code "535" +``` + +**Solutions**: +- Verify username and password +- Use App Password for Gmail +- Check if 2FA is enabled and requires app password + +#### "From address not allowed" +``` +Message: From address not allowed +``` + +**Solutions**: +- Ensure `MAIL_FROM_ADDRESS` matches authenticated user +- Configure your email provider to allow sending from this address +- Use provider's verified domain + +### Debug Mode + +Enable email debugging: + +```bash +# Add to environment +LOG_LEVEL=debug +MAIL_LOG_CHANNEL=single + +# Check detailed logs +docker logs authentikate | grep -i mail +``` + +### Test with Different Providers + +If one provider doesn't work, try another: + +```bash +# Try Gmail first (easiest to set up) +MAIL_HOST=smtp.gmail.com + +# Then try SendGrid (good for production) +MAIL_HOST=smtp.sendgrid.net + +# Or use a transactional service +MAIL_HOST=smtp.mailgun.org +``` + +## Production Recommendations + +### Dedicated Email Service +For production, use a dedicated email service: +- **SendGrid**: Easy setup, good deliverability +- **Mailgun**: Reliable, detailed analytics +- **Amazon SES**: Cost-effective, AWS integration +- **Postmark**: Fast delivery, great for transactional emails + +### Domain Authentication +Set up SPF, DKIM, and DMARC records: + +```dns +# SPF record +yourdomain.com. TXT "v=spf1 include:_spf.google.com ~all" + +# DKIM (provided by email service) +default._domainkey.yourdomain.com. TXT "v=DKIM1; k=rsa; p=..." + +# DMARC +_dmarc.yourdomain.com. TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" +``` + +### Monitoring +Monitor email delivery: +- Track bounce rates +- Monitor spam complaints +- Watch delivery statistics +- Set up alerts for failures + +Your email configuration is now ready! Users will receive professional-looking emails for invitations, password resets, and other notifications. \ No newline at end of file diff --git a/docs/config/environment.md b/docs/config/environment.md new file mode 100644 index 0000000..b1a3825 --- /dev/null +++ b/docs/config/environment.md @@ -0,0 +1,402 @@ +# Environment Variables + +AuthentiKate is configured through environment variables. This page covers all available configuration options. + +## Core Application Settings + +### APP_URL +**Required** - The URL where AuthentiKate is accessible. + +```bash +APP_URL=https://auth.yourdomain.com +``` + +::: warning +This URL must match exactly how users access AuthentiKate. OAuth redirects and JWT tokens depend on this value. +::: + +### APP_ENV +**Default**: `production` + +```bash +APP_ENV=production # or 'local' for development +``` + +### APP_DEBUG +**Default**: `false` + +```bash +APP_DEBUG=false # Set to 'true' only for debugging +``` + +::: danger +Never set `APP_DEBUG=true` in production as it exposes sensitive information. +::: + +### APP_KEY +**Auto-generated** - Laravel application key for encryption. + +```bash +APP_KEY=base64:generated-key-here +``` + +The key is automatically generated on first run. Do not change this after deployment as it will invalidate existing sessions and tokens. + +## Database Configuration + +### SQLite (Default) + +```bash +DB_CONNECTION=sqlite +DB_DATABASE=/var/www/html/storage/database/database.sqlite +``` + +### PostgreSQL + +```bash +DB_CONNECTION=pgsql +DB_HOST=postgres +DB_PORT=5432 +DB_DATABASE=authentikate +DB_USERNAME=authentikate +DB_PASSWORD=secure_password +``` + +### MySQL/MariaDB + +```bash +DB_CONNECTION=mysql +DB_HOST=mysql +DB_PORT=3306 +DB_DATABASE=authentikate +DB_USERNAME=authentikate +DB_PASSWORD=secure_password +``` + +## Email Configuration + +Email is used for user invitations, password resets, and verification. + +### SMTP + +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@gmail.com +MAIL_PASSWORD=your-app-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="AuthentiKate" +``` + +### Common SMTP Providers + +#### Gmail +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@gmail.com +MAIL_PASSWORD=your-app-password # Use App Password, not regular password +MAIL_ENCRYPTION=tls +``` + +#### Outlook/Hotmail +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp-mail.outlook.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@outlook.com +MAIL_PASSWORD=your-password +MAIL_ENCRYPTION=tls +``` + +#### SendGrid +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.sendgrid.net +MAIL_PORT=587 +MAIL_USERNAME=apikey +MAIL_PASSWORD=your-sendgrid-api-key +MAIL_ENCRYPTION=tls +``` + +#### Mailgun +```bash +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailgun.org +MAIL_PORT=587 +MAIL_USERNAME=your-mailgun-username +MAIL_PASSWORD=your-mailgun-password +MAIL_ENCRYPTION=tls +``` + +### Disable Email +```bash +MAIL_MAILER=log # Emails will be written to logs instead of sent +``` + +## Cache Configuration + +### Redis (Recommended for Production) + +```bash +CACHE_DRIVER=redis +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_PASSWORD=your-redis-password +``` + +### File Cache (Default) + +```bash +CACHE_DRIVER=file +``` + +### Database Cache + +```bash +CACHE_DRIVER=database +``` + +## Session Configuration + +### Redis Sessions (Recommended for Production) + +```bash +SESSION_DRIVER=redis +SESSION_LIFETIME=120 # Minutes +``` + +### File Sessions (Default) + +```bash +SESSION_DRIVER=file +SESSION_LIFETIME=120 +``` + +### Database Sessions + +```bash +SESSION_DRIVER=database +``` + +## Security Settings + +### SSL/HTTPS + +```bash +# Force HTTPS redirects +FORCE_HTTPS=true + +# Set secure cookie settings +SESSION_SECURE_COOKIE=true +SANCTUM_STATEFUL_DOMAINS=auth.yourdomain.com +``` + +### CORS Configuration + +```bash +# Allow CORS for your domains +CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://app.yourdomain.com +``` + +## Logging + +### Log Level + +```bash +LOG_LEVEL=info # debug, info, notice, warning, error, critical, alert, emergency +``` + +### Log Channel + +```bash +LOG_CHANNEL=stack # single, daily, slack, syslog, errorlog +``` + +### Daily Log Rotation + +```bash +LOG_CHANNEL=daily +LOG_DAILY_DAYS=14 # Keep logs for 14 days +``` + +## Queue Configuration + +For background job processing: + +### Redis Queue + +```bash +QUEUE_CONNECTION=redis +``` + +### Database Queue + +```bash +QUEUE_CONNECTION=database +``` + +### Sync Queue (Default) + +```bash +QUEUE_CONNECTION=sync # Process jobs immediately +``` + +## OAuth/OIDC Settings + +### Token Lifetimes + +```bash +# Access token lifetime (in minutes) +OAUTH_ACCESS_TOKEN_LIFETIME=60 + +# Refresh token lifetime (in days) +OAUTH_REFRESH_TOKEN_LIFETIME=30 + +# Authorization code lifetime (in minutes) +OAUTH_AUTHORIZATION_CODE_LIFETIME=10 +``` + +### JWT Configuration + +```bash +# JWT algorithm (default: RS256) +JWT_ALGORITHM=RS256 + +# Key paths (automatically set) +OAUTH_PRIVATE_KEY_PATH=storage/oauth/private.pem +OAUTH_PUBLIC_KEY_PATH=storage/oauth/public.pem +``` + +## Performance Settings + +### PHP Configuration + +```bash +# Memory limit +PHP_MEMORY_LIMIT=256M + +# Upload limits +PHP_UPLOAD_MAX_FILESIZE=10M +PHP_POST_MAX_SIZE=10M + +# Execution time +PHP_MAX_EXECUTION_TIME=300 +``` + +### Application Optimization + +```bash +# Enable optimizations for production +APP_OPTIMIZE=true + +# Cache configuration +CONFIG_CACHE=true +ROUTE_CACHE=true +VIEW_CACHE=true +``` + +## Development Settings + +These should only be used in development environments: + +```bash +APP_ENV=local +APP_DEBUG=true +LOG_LEVEL=debug + +# Disable HTTPS for local development +FORCE_HTTPS=false +SESSION_SECURE_COOKIE=false +``` + +## Complete Production Example + +Here's a complete environment configuration for production: + +```bash +# Application +APP_ENV=production +APP_DEBUG=false +APP_URL=https://auth.yourdomain.com +FORCE_HTTPS=true + +# Database +DB_CONNECTION=pgsql +DB_HOST=postgres +DB_DATABASE=authentikate +DB_USERNAME=authentikate +DB_PASSWORD=secure_database_password + +# Email +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=auth@yourdomain.com +MAIL_PASSWORD=gmail_app_password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=auth@yourdomain.com +MAIL_FROM_NAME="Your Company Auth" + +# Cache & Sessions +CACHE_DRIVER=redis +SESSION_DRIVER=redis +REDIS_HOST=redis +REDIS_PASSWORD=secure_redis_password + +# Security +SESSION_SECURE_COOKIE=true +SESSION_LIFETIME=120 +SANCTUM_STATEFUL_DOMAINS=yourdomain.com + +# Performance +LOG_LEVEL=warning +LOG_CHANNEL=daily +LOG_DAILY_DAYS=30 +``` + +## Docker Compose Integration + +Add environment variables to your `docker-compose.yml`: + +```yaml +services: + authentikate: + image: authentikate/authentikate:latest + environment: + - APP_URL=https://auth.yourdomain.com + - APP_ENV=production + - DB_CONNECTION=pgsql + - DB_HOST=postgres + - MAIL_MAILER=smtp + - MAIL_HOST=smtp.gmail.com + # ... other variables + env_file: + - .env # Or load from file +``` + +## Environment File + +Create a `.env` file for easier management: + +```bash +# Create environment file +cat > .env << 'EOF' +APP_URL=https://auth.yourdomain.com +APP_ENV=production +DB_CONNECTION=pgsql +# ... other settings +EOF + +# Reference in docker-compose.yml +services: + authentikate: + env_file: .env +``` + +::: tip +Keep your `.env` file secure and never commit it to version control. +::: \ No newline at end of file diff --git a/docs/guide/applications.md b/docs/guide/applications.md new file mode 100644 index 0000000..6e6e800 --- /dev/null +++ b/docs/guide/applications.md @@ -0,0 +1,188 @@ +# Managing Applications + +Learn how to create and manage OAuth applications in AuthentiKate. + +## Creating Applications + +### Via Web Interface + +1. **Navigate** to **Applications** in the admin panel +2. **Click** "Create Application" +3. **Fill in** the application details: + - **Name**: Display name for your application + - **Redirect URI**: OAuth callback URL + - **Icon**: Optional icon URL for the application +4. **Save** the application + +### Application Details + +Each application gets: +- **Unique Client ID**: Public identifier for your application +- **Client Secret**: Private key for token exchange +- **Redirect URI**: Where users return after authentication + +::: warning +Keep your Client Secret secure! It should never be exposed in client-side code. +::: + +## Application Templates + +AuthentiKate includes templates for popular applications: + +### Available Templates +- **Grafana**: Analytics and monitoring +- **Nextcloud**: File sharing and collaboration +- **Proxmox**: Virtualization management +- **Portainer**: Docker container management +- **GitLab**: Git repository hosting + +Templates automatically configure: +- Correct redirect URI patterns +- Appropriate application icons +- Common configuration settings + +## OAuth Configuration + +### Client Credentials +```yaml +Client ID: f47ac10b-58cc-4372-a567-0e02b2c3d479 +Client Secret: 40-character-random-string +``` + +### Endpoints +Your applications will use these endpoints: +- **Authorization**: `/oauth/authorize` +- **Token**: `/oauth/token` +- **User Info**: `/oauth/userinfo` +- **JWKS**: `/.well-known/jwks.json` + +### Supported Features +- **Authorization Code Flow**: Standard OAuth2 flow +- **PKCE**: Enhanced security for public clients +- **JWT Tokens**: Signed with RSA256 +- **Refresh Tokens**: Long-lived token renewal + +## Security Best Practices + +### Redirect URI Validation +- Use exact URI matching +- Always use HTTPS in production +- Avoid wildcard redirects + +### Client Secret Management +- Store secrets securely +- Rotate secrets regularly +- Use different secrets per environment + +### Token Handling +- Validate token signatures +- Respect token expiration +- Implement proper logout + +## Common Integration Patterns + +### Server-Side Applications +Best for applications that can securely store client secrets: + +```javascript +// Example: Node.js application +const config = { + clientId: 'your-client-id', + clientSecret: 'your-client-secret', + authorizationURL: 'https://auth.yourdomain.com/oauth/authorize', + tokenURL: 'https://auth.yourdomain.com/oauth/token', + callbackURL: 'https://yourapp.com/auth/callback' +}; +``` + +### Single Page Applications (SPA) +For client-side applications using PKCE: + +```javascript +// Example: React application with PKCE +const config = { + clientId: 'your-client-id', + // No client secret for public clients + authorizationURL: 'https://auth.yourdomain.com/oauth/authorize', + tokenURL: 'https://auth.yourdomain.com/oauth/token', + redirectUri: 'https://yourapp.com/callback', + usePKCE: true +}; +``` + +### Mobile Applications +Similar to SPAs, always use PKCE: + +```swift +// Example: iOS Swift +let config = OIDServiceConfiguration( + authorizationEndpoint: URL(string: "https://auth.yourdomain.com/oauth/authorize")!, + tokenEndpoint: URL(string: "https://auth.yourdomain.com/oauth/token")! +) +``` + +## Testing Applications + +### Manual Testing +1. **Start OAuth flow** from your application +2. **Verify redirect** to AuthentiKate +3. **Complete authentication** +4. **Confirm successful** return to your app +5. **Check user data** is populated correctly + +### Automated Testing +```bash +# Test authorization endpoint +curl "https://auth.yourdomain.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=openid" + +# Test token exchange (after getting auth code) +curl -X POST https://auth.yourdomain.com/oauth/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=authorization_code&code=AUTH_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=REDIRECT_URI" +``` + +## Troubleshooting + +### Invalid Redirect URI +**Error**: `The redirect URI is invalid` + +**Solutions**: +- Verify exact URL match in application settings +- Check for trailing slashes +- Ensure HTTPS is used + +### Invalid Client +**Error**: `Client authentication failed` + +**Solutions**: +- Verify Client ID and Secret +- Check that application exists and is active +- Ensure secrets haven't been regenerated + +### Token Validation Issues +**Error**: `Invalid token signature` + +**Solutions**: +- Use JWKS endpoint for signature validation +- Verify token hasn't expired +- Check token issuer matches AuthentiKate URL + +## Application Management + +### Updating Applications +- **Edit** application details anytime +- **Regenerate** client secrets if compromised +- **Update** redirect URIs for new environments + +### Deactivating Applications +- **Disable** applications to prevent new logins +- Existing tokens remain valid until expiration +- **Re-enable** anytime to restore access + +### Monitoring Usage +View application usage in the admin panel: +- **Active tokens** per application +- **Recent authentications** +- **User access patterns** + +Your applications are now ready for OAuth integration with AuthentiKate! \ No newline at end of file diff --git a/docs/guide/first-setup.md b/docs/guide/first-setup.md new file mode 100644 index 0000000..b0225f5 --- /dev/null +++ b/docs/guide/first-setup.md @@ -0,0 +1,202 @@ +# First Setup + +After installing AuthentiKate, you'll want to complete the initial configuration to make it ready for production use. + +## Initial Login + +When you first start AuthentiKate, it automatically creates an admin user. The credentials are shown in the container logs: + +```bash +docker logs authentikate +``` + +Look for: +``` +✅ Initial admin user created: + Email: admin@authentikate.local + Password: randomly-generated-password +``` + +::: tip +Save these credentials securely! You'll need them to access the admin interface. +::: + +## Admin Dashboard + +After logging in, you'll see the AuthentiKate dashboard with: + +- **Applications**: Manage OAuth applications +- **Users**: User management and invitations +- **Tokens**: View active authentication tokens +- **Profile**: Your user profile settings + +## Essential Configuration Steps + +### 1. Update Your Profile + +1. Click your avatar in the top right +2. Select **"Profile"** +3. Update your information: + - Change the email from `admin@authentikate.local` to your real email + - Set a preferred username + - Upload an avatar (optional) + - **Change your password** to something secure + +### 2. Configure Email (Recommended) + +Email is used for: +- User invitations +- Password resets +- Account verification + +Set up email by updating your environment variables: + +```yaml +environment: + MAIL_MAILER: smtp + MAIL_HOST: smtp.gmail.com + MAIL_PORT: 587 + MAIL_USERNAME: your-email@gmail.com + MAIL_PASSWORD: your-app-password + MAIL_ENCRYPTION: tls + MAIL_FROM_ADDRESS: auth@yourdomain.com + MAIL_FROM_NAME: "AuthentiKate" +``` + +[→ See full email configuration guide](/config/email) + +### 3. Set Your Domain + +Update the `APP_URL` to match your actual domain: + +```yaml +environment: + APP_URL: https://auth.yourdomain.com +``` + +This ensures: +- Correct OAuth redirect URLs +- Proper JWT issuer claims +- Working email links + +### 4. Create Your First Application + +1. Go to **Applications** → **Create Application** +2. Fill in the basic information: + - **Name**: Your application name (e.g., "Grafana") + - **Redirect URI**: Where users return after authentication + - **Icon**: Optional app icon URL + +3. Note the generated **Client ID** and **Client Secret** +4. Use these in your application's OAuth configuration + +## Security Checklist + +Before going to production, verify these security settings: + +### ✅ Admin Account +- [ ] Changed default admin email +- [ ] Set a strong, unique password +- [ ] Enabled email verification (if email is configured) + +### ✅ Environment +- [ ] Set `APP_ENV=production` +- [ ] Set `APP_DEBUG=false` +- [ ] Using HTTPS with valid SSL certificate +- [ ] `APP_URL` matches your actual domain + +### ✅ Database +- [ ] Using persistent volume for data +- [ ] Consider using PostgreSQL/MySQL for production +- [ ] Regular backups configured + +### ✅ Reverse Proxy +- [ ] Proper SSL termination +- [ ] Security headers configured +- [ ] Rate limiting in place + +## Application Integration + +### OIDC Endpoints + +Your applications will need these endpoints: + +| Endpoint | URL | +|----------|-----| +| Authorization | `https://auth.yourdomain.com/oauth/authorize` | +| Token | `https://auth.yourdomain.com/oauth/token` | +| User Info | `https://auth.yourdomain.com/oauth/userinfo` | +| JWKS | `https://auth.yourdomain.com/.well-known/jwks.json` | +| Discovery | `https://auth.yourdomain.com/.well-known/openid_configuration` | + +### OAuth Flow + +1. **User clicks login** in your application +2. **Redirect to AuthentiKate** with authorization request +3. **User authenticates** (if not already logged in) +4. **User consents** to application access (if required) +5. **Redirect back** to your application with authorization code +6. **Exchange code** for access token and ID token +7. **Access user info** using the access token + +## User Management + +### Invitation System + +AuthentiKate uses an invitation-based registration system: + +1. **Admin creates invitation** with user's email +2. **Invitation email sent** with registration link +3. **User completes registration** using the invitation +4. **User can access applications** they're authorized for + +### User Permissions + +- **Admin users**: Full access to manage applications and users +- **Regular users**: Can only access authorized applications and manage their own profile + +## Backup Strategy + +Set up regular backups of your AuthentiKate data: + +### SQLite (Default) +```bash +# Daily backup script +#!/bin/bash +docker exec authentikate cp /var/www/html/storage/database/database.sqlite /tmp/backup.sqlite +docker cp authentikate:/tmp/backup.sqlite ./backups/authentikate-$(date +%Y%m%d).sqlite +``` + +### Full Volume Backup +```bash +# Backup all persistent data +docker run --rm -v authentikate_data:/data -v $(pwd)/backups:/backup alpine tar czf /backup/authentikate-full-$(date +%Y%m%d).tar.gz -C /data . +``` + +## Common Next Steps + +### Popular Integrations +- [Set up Grafana SSO](/integrations/grafana) +- [Configure Nextcloud authentication](/integrations/nextcloud) +- [Integrate with Traefik forward auth](/integrations/traefik) + +### Advanced Configuration +- [Environment variables reference](/config/environment) +- [Database configuration](/config/database) +- [Security settings](/config/security) + +### User Management +- [Create user invitations](/guide/invitations) +- [Manage user profiles](/guide/profiles) +- [Handle user permissions](/guide/users) + +## Getting Help + +If you run into issues: + +1. **Check the logs**: `docker logs authentikate` +2. **Verify configuration**: Compare with working examples +3. **Test endpoints**: Use curl or Postman to test OIDC endpoints +4. **Community support**: Check GitHub issues and discussions + +Your AuthentiKate instance is now ready for production use! 🎉 \ No newline at end of file diff --git a/docs/guide/installation.md b/docs/guide/installation.md new file mode 100644 index 0000000..0d2d914 --- /dev/null +++ b/docs/guide/installation.md @@ -0,0 +1,259 @@ +# Installation + +AuthentiKate is designed to be deployed easily with Docker, making it perfect for homelab environments. This guide will walk you through different installation methods. + +## Quick Start with Docker + +The fastest way to get AuthentiKate running is with Docker: + +```bash +docker run -d \ + --name authentikate \ + -p 8080:8080 \ + -e APP_URL=http://localhost:8080 \ + -v authentikate_data:/var/www/html/storage \ + authentikate/authentikate:latest +``` + +AuthentiKate will be available at `http://localhost:8080` with automatic setup completing in the background. + +## Docker Compose (Recommended) + +For production use, we recommend using Docker Compose for better configuration management: + +```yaml +version: '3.8' + +services: + authentikate: + image: authentikate/authentikate:latest + container_name: authentikate + restart: unless-stopped + ports: + - "8080:8080" + environment: + # Required + APP_URL: https://auth.yourdomain.com + APP_ENV: production + + # Database (SQLite by default) + DB_CONNECTION: sqlite + + # Email (optional but recommended) + MAIL_MAILER: smtp + MAIL_HOST: your-smtp-server.com + MAIL_PORT: 587 + MAIL_USERNAME: your-email@domain.com + MAIL_PASSWORD: your-password + MAIL_ENCRYPTION: tls + MAIL_FROM_ADDRESS: auth@yourdomain.com + MAIL_FROM_NAME: "AuthentiKate" + + volumes: + - authentikate_data:/var/www/html/storage + - authentikate_logs:/var/www/html/storage/logs + + # Optional: Use external database + # depends_on: + # - postgres + + labels: + # Traefik labels (if using Traefik) + - "traefik.enable=true" + - "traefik.http.routers.authentikate.rule=Host(`auth.yourdomain.com`)" + - "traefik.http.routers.authentikate.entrypoints=websecure" + - "traefik.http.routers.authentikate.tls.certresolver=letsencrypt" + - "traefik.http.services.authentikate.loadbalancer.server.port=8080" + +volumes: + authentikate_data: + authentikate_logs: +``` + +## Environment Variables + +### Required Variables + +| Variable | Description | Example | +|----------|-------------|---------| +| `APP_URL` | The URL where AuthentiKate will be accessible | `https://auth.yourdomain.com` | + +### Optional Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `APP_ENV` | `production` | Application environment | +| `APP_DEBUG` | `false` | Enable debug mode | +| `DB_CONNECTION` | `sqlite` | Database type (`sqlite`, `mysql`, `postgres`) | +| `DB_DATABASE` | `/var/www/html/storage/database/database.sqlite` | Database path/name | + +## Database Options + +### SQLite (Default) +Perfect for most homelab setups. No additional configuration required. + +### PostgreSQL +For larger installations: + +```yaml +services: + postgres: + image: postgres:15 + environment: + POSTGRES_DB: authentikate + POSTGRES_USER: authentikate + POSTGRES_PASSWORD: secure_password + volumes: + - postgres_data:/var/lib/postgresql/data + + authentikate: + # ... other config + environment: + DB_CONNECTION: pgsql + DB_HOST: postgres + DB_DATABASE: authentikate + DB_USERNAME: authentikate + DB_PASSWORD: secure_password + depends_on: + - postgres + +volumes: + postgres_data: +``` + +### MySQL/MariaDB +```yaml +services: + mysql: + image: mariadb:10 + environment: + MYSQL_DATABASE: authentikate + MYSQL_USER: authentikate + MYSQL_PASSWORD: secure_password + MYSQL_ROOT_PASSWORD: root_password + volumes: + - mysql_data:/var/lib/mysql + + authentikate: + # ... other config + environment: + DB_CONNECTION: mysql + DB_HOST: mysql + DB_DATABASE: authentikate + DB_USERNAME: authentikate + DB_PASSWORD: secure_password + depends_on: + - mysql + +volumes: + mysql_data: +``` + +## Reverse Proxy Setup + +### Traefik +AuthentiKate works perfectly with Traefik. Add these labels to your Docker Compose: + +```yaml +labels: + - "traefik.enable=true" + - "traefik.http.routers.authentikate.rule=Host(`auth.yourdomain.com`)" + - "traefik.http.routers.authentikate.entrypoints=websecure" + - "traefik.http.routers.authentikate.tls.certresolver=letsencrypt" + - "traefik.http.services.authentikate.loadbalancer.server.port=8080" +``` + +### Nginx +```nginx +server { + listen 443 ssl http2; + server_name auth.yourdomain.com; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://localhost:8080; + 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; + } +} +``` + +### Caddy +```caddyfile +auth.yourdomain.com { + reverse_proxy localhost:8080 +} +``` + +## First Run + +When you first start AuthentiKate, it will automatically: + +1. **Generate RSA Keys**: Creates public/private key pair for JWT signing +2. **Run Database Migrations**: Sets up all necessary database tables +3. **Create Admin User**: Generates an initial admin account + +The initial admin credentials will be displayed in the container logs: + +```bash +docker logs authentikate +``` + +Look for output like: +``` +✅ Initial admin user created: + Email: admin@authentikate.local + Password: randomly-generated-password +``` + +## Updating + +To update AuthentiKate: + +```bash +# Pull the latest image +docker pull authentikate/authentikate:latest + +# Stop and remove the old container +docker stop authentikate +docker rm authentikate + +# Start with the new image +docker-compose up -d +``` + +Your data will be preserved in the Docker volumes. + +## Backup + +### Database Backup (SQLite) +```bash +# Create backup +docker exec authentikate cp /var/www/html/storage/database/database.sqlite /tmp/backup.sqlite +docker cp authentikate:/tmp/backup.sqlite ./authentikate-backup-$(date +%Y%m%d).sqlite + +# Restore backup +docker cp ./authentikate-backup-20240101.sqlite authentikate:/tmp/restore.sqlite +docker exec authentikate cp /tmp/restore.sqlite /var/www/html/storage/database/database.sqlite +``` + +### Full Data Backup +```bash +# Backup all data +docker run --rm -v authentikate_data:/data -v $(pwd):/backup alpine tar czf /backup/authentikate-data-$(date +%Y%m%d).tar.gz -C /data . + +# Restore data +docker run --rm -v authentikate_data:/data -v $(pwd):/backup alpine tar xzf /backup/authentikate-data-20240101.tar.gz -C /data +``` + +## Next Steps + +Once AuthentiKate is running: + +1. [Complete the first setup →](/guide/first-setup) +2. [Configure your first application →](/guide/applications) +3. [Set up email notifications →](/config/email) \ No newline at end of file diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md new file mode 100644 index 0000000..06e8ef8 --- /dev/null +++ b/docs/guide/quick-start.md @@ -0,0 +1,159 @@ +# Quick Start + +This guide will get you up and running with AuthentiKate in under 5 minutes. + +## Prerequisites + +- Docker installed on your system +- A domain name (optional, can use localhost for testing) + +## Step 1: Deploy AuthentiKate + +Run the following command to start AuthentiKate: + +```bash +docker run -d \ + --name authentikate \ + -p 8080:8080 \ + -e APP_URL=http://localhost:8080 \ + -v authentikate_data:/var/www/html/storage \ + authentikate/authentikate:latest +``` + +## Step 2: Get Your Admin Credentials + +AuthentiKate automatically creates an admin user on first run. Get the credentials from the logs: + +```bash +docker logs authentikate +``` + +Look for output like: +``` +✅ Initial admin user created: + Email: admin@authentikate.local + Password: Xy9#mK2$vB8nQ4!p +``` + +## Step 3: Access the Interface + +1. Open your browser and go to `http://localhost:8080` +2. Log in with the admin credentials from Step 2 +3. You'll be taken to the AuthentiKate dashboard + +## Step 4: Create Your First Application + +1. Click **"Applications"** in the navigation +2. Click **"Create Application"** +3. Fill in the details: + - **Name**: `Test App` + - **Redirect URI**: `http://localhost:3000/auth/callback` + - **Client ID**: (auto-generated) + - **Client Secret**: (auto-generated) + +4. Click **"Save"** + +## Step 5: Test the Integration + +Your application is now configured! Here are the OIDC endpoints you'll need: + +- **Authorization**: `http://localhost:8080/oauth/authorize` +- **Token**: `http://localhost:8080/oauth/token` +- **User Info**: `http://localhost:8080/oauth/userinfo` +- **JWKS**: `http://localhost:8080/.well-known/jwks.json` +- **Discovery**: `http://localhost:8080/.well-known/openid_configuration` + +## Common Integration Examples + +### Test with curl + +```bash +# Get authorization URL (replace CLIENT_ID with your actual client ID) +CLIENT_ID="your-client-id" +REDIRECT_URI="http://localhost:3000/auth/callback" + +echo "Visit this URL to authorize:" +echo "http://localhost:8080/oauth/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=openid profile email" +``` + +### Simple HTML Test Page + +Create a simple test page to try the OAuth flow: + +```html + + + + AuthentiKate Test + + +

AuthentiKate OAuth Test

+ + + + + +``` + +## What's Next? + +Now that you have AuthentiKate running: + +### Configure Your Environment +- [Set up email notifications](/config/email) +- [Configure a custom domain](/config/environment) +- [Set up reverse proxy](/guide/installation#reverse-proxy-setup) + +### Add Real Applications +- [Integrate with Grafana](/integrations/grafana) +- [Set up Nextcloud SSO](/integrations/nextcloud) +- [Configure other applications](/integrations/generic) + +### Manage Users +- [Create user invitations](/guide/invitations) +- [Set up user profiles](/guide/profiles) +- [Configure user permissions](/guide/users) + +### Production Setup +- [Use PostgreSQL/MySQL](/guide/installation#database-options) +- [Set up proper email](/config/email) +- [Configure security settings](/config/security) + +## Troubleshooting + +### Can't access AuthentiKate? +- Make sure the container is running: `docker ps` +- Check the logs: `docker logs authentikate` +- Verify the port is accessible: `curl http://localhost:8080` + +### Forgot admin password? +Reset it by running: +```bash +docker exec -it authentikate php artisan app:create-initial-admin --force +``` + +### Need to change the URL? +Update the `APP_URL` environment variable and restart: +```bash +docker stop authentikate +docker rm authentikate +# Run again with new APP_URL +``` + +### Container won't start? +Check for port conflicts: +```bash +# See what's using port 8080 +sudo netstat -tulpn | grep 8080 + +# Use a different port +docker run -d --name authentikate -p 8081:8080 ... +``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..d4d206d --- /dev/null +++ b/docs/index.md @@ -0,0 +1,75 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "AuthentiKate" + text: "SSO/OIDC for Homelabbers" + tagline: A lightweight, self-hosted authentication solution that just works + image: + src: /logo.svg + alt: AuthentiKate + actions: + - theme: brand + text: Get Started + link: /guide/installation + - theme: alt + text: View on GitHub + link: https://github.com/jdubpark/authentikate + +features: + - icon: 🔐 + title: OpenID Connect Ready + details: Full OIDC compliance with JWT tokens, PKCE support, and industry-standard security practices. Integrate with any OAuth2/OIDC compatible application. + + - icon: 🐳 + title: Docker First + details: Single container deployment with automatic setup. No complex configuration files or multi-service orchestration required. + + - icon: ⚡ + title: Built for Speed + details: Powered by Laravel and optimized for homelab environments. Fast authentication flows and minimal resource usage. + + - icon: 🎨 + title: Beautiful Interface + details: Clean, modern UI built with Livewire and Tailwind CSS. Intuitive user management and application configuration. + + - icon: 🔄 + title: Auto-Configuration + details: Automatic RSA key generation, database setup, and admin user creation. Zero manual configuration needed. + + - icon: 🏠 + title: Homelab Optimized + details: Perfect for self-hosters. Integrates seamlessly with Traefik, includes popular app presets, and supports local networks. + + - icon: 👥 + title: User Management + details: Invitation-based registration, user profiles with avatars, and granular permission controls. Keep your homelab secure. + + - icon: 📱 + title: Modern Features + details: JWT tokens with UUID-based user identification, token management, and comprehensive audit logging. +--- + +## Why AuthentiKate? + +AuthentiKate is designed specifically for homelabbers who want enterprise-grade authentication without the enterprise complexity. Unlike heavyweight solutions that require extensive setup and maintenance, AuthentiKate gets you up and running in minutes. + +### Perfect for Your Homelab + +- **One Container**: Deploy with a single Docker command +- **Zero Config**: Automatic setup with sensible defaults +- **Popular Apps**: Pre-configured templates for Grafana, Nextcloud, and more +- **Reverse Proxy Ready**: Works seamlessly with Traefik and other proxies + +### Enterprise Features, Homelab Simplicity + +- Full OpenID Connect compliance +- JWT tokens with RSA256 signing +- PKCE support for mobile apps +- Invitation-based user registration +- Comprehensive token management +- Beautiful, responsive interface + +Ready to secure your homelab? [Get started in minutes →](/guide/installation) + diff --git a/docs/integrations/grafana.md b/docs/integrations/grafana.md new file mode 100644 index 0000000..242359d --- /dev/null +++ b/docs/integrations/grafana.md @@ -0,0 +1,322 @@ +# Grafana Integration + +This guide shows how to integrate Grafana with AuthentiKate for single sign-on authentication. + +## Prerequisites + +- AuthentiKate running and accessible +- Grafana instance (Docker or standalone) +- Admin access to both systems + +## Step 1: Create Application in AuthentiKate + +1. Log into your AuthentiKate admin panel +2. Navigate to **Applications** → **Create Application** +3. Fill in the application details: + +``` +Name: Grafana +Redirect URI: https://grafana.yourdomain.com/login/generic_oauth +Icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/grafana.webp +``` + +4. Click **Save** and note the generated: + - **Client ID** + - **Client Secret** + +## Step 2: Configure Grafana + +### Environment Variables (Docker) + +Add these environment variables to your Grafana container: + +```yaml +services: + grafana: + image: grafana/grafana:latest + environment: + # OAuth Settings + GF_AUTH_GENERIC_OAUTH_ENABLED: "true" + GF_AUTH_GENERIC_OAUTH_NAME: "AuthentiKate" + GF_AUTH_GENERIC_OAUTH_CLIENT_ID: "your-client-id" + GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: "your-client-secret" + GF_AUTH_GENERIC_OAUTH_SCOPES: "openid profile email" + GF_AUTH_GENERIC_OAUTH_AUTH_URL: "https://auth.yourdomain.com/oauth/authorize" + GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "https://auth.yourdomain.com/oauth/token" + GF_AUTH_GENERIC_OAUTH_API_URL: "https://auth.yourdomain.com/oauth/userinfo" + + # Auto-login (optional) + GF_AUTH_OAUTH_AUTO_LOGIN: "true" + GF_AUTH_DISABLE_LOGIN_FORM: "true" + + # User mapping + GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH: "preferred_username" + GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH: "name" + GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH: "email" + + # Role mapping (optional) + GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: "contains(groups[*], 'admin') && 'Admin' || 'Viewer'" +``` + +### Configuration File + +Alternatively, configure via `grafana.ini`: + +```ini +[auth.generic_oauth] +enabled = true +name = AuthentiKate +client_id = your-client-id +client_secret = your-client-secret +scopes = openid profile email +auth_url = https://auth.yourdomain.com/oauth/authorize +token_url = https://auth.yourdomain.com/oauth/token +api_url = https://auth.yourdomain.com/oauth/userinfo + +# Auto-login +auto_login = true + +# User attribute mapping +login_attribute_path = preferred_username +name_attribute_path = name +email_attribute_path = email + +# Role mapping (optional) +role_attribute_path = contains(groups[*], 'admin') && 'Admin' || 'Viewer' + +[auth] +# Disable regular login form (optional) +disable_login_form = true +# Allow sign up +oauth_auto_login = true +``` + +## Step 3: Docker Compose Example + +Complete Docker Compose configuration: + +```yaml +version: '3.8' + +services: + grafana: + image: grafana/grafana:latest + container_name: grafana + restart: unless-stopped + ports: + - "3000:3000" + environment: + # Basic settings + GF_SECURITY_ADMIN_PASSWORD: admin + GF_INSTALL_PLUGINS: grafana-piechart-panel + + # OAuth with AuthentiKate + GF_AUTH_GENERIC_OAUTH_ENABLED: "true" + GF_AUTH_GENERIC_OAUTH_NAME: "AuthentiKate" + GF_AUTH_GENERIC_OAUTH_CLIENT_ID: "your-client-id-here" + GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: "your-client-secret-here" + GF_AUTH_GENERIC_OAUTH_SCOPES: "openid profile email" + GF_AUTH_GENERIC_OAUTH_AUTH_URL: "https://auth.yourdomain.com/oauth/authorize" + GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "https://auth.yourdomain.com/oauth/token" + GF_AUTH_GENERIC_OAUTH_API_URL: "https://auth.yourdomain.com/oauth/userinfo" + + # User mapping + GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH: "preferred_username" + GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH: "name" + GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH: "email" + + # Auto-login + GF_AUTH_OAUTH_AUTO_LOGIN: "true" + GF_AUTH_DISABLE_LOGIN_FORM: "false" # Keep false for admin access + + volumes: + - grafana_data:/var/lib/grafana + + labels: + # Traefik labels (if using Traefik) + - "traefik.enable=true" + - "traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)" + - "traefik.http.routers.grafana.entrypoints=websecure" + - "traefik.http.routers.grafana.tls.certresolver=letsencrypt" + +volumes: + grafana_data: +``` + +## Step 4: Advanced Configuration + +### Role Mapping + +Map AuthentiKate users to Grafana roles based on user attributes: + +```ini +# Basic role mapping +role_attribute_path = preferred_username == 'admin' && 'Admin' || 'Viewer' + +# Multiple admin users +role_attribute_path = contains(['admin', 'grafana-admin'], preferred_username) && 'Admin' || 'Editor' + +# Default to Editor for all users +role_attribute_path = 'Editor' +``` + +### Team Mapping + +Automatically assign users to Grafana teams: + +```ini +# Team mapping (if you add groups to AuthentiKate in the future) +team_ids_attribute_path = groups +team_ids = 1,2,3 +``` + +### Allow Sign-Up + +Control whether new users can sign up automatically: + +```ini +[users] +# Allow users to sign up +allow_sign_up = true + +# Auto-assign organization +auto_assign_org = true +auto_assign_org_id = 1 + +# Default role for new users +auto_assign_org_role = Viewer +``` + +## Step 5: Testing + +1. **Restart Grafana** after configuration changes +2. **Navigate to Grafana** in your browser +3. **Click "Sign in with AuthentiKate"** (or get redirected automatically) +4. **Authenticate with AuthentiKate** using your credentials +5. **Verify** you're logged into Grafana with the correct user info + +## Troubleshooting + +### Common Issues + +#### "Invalid redirect URI" Error +Ensure the redirect URI in AuthentiKate exactly matches: +``` +https://grafana.yourdomain.com/login/generic_oauth +``` + +#### Users Not Getting Correct Roles +Check the role mapping configuration: +```ini +# Debug role mapping +role_attribute_path = 'Admin' # Give everyone admin temporarily +``` + +#### OAuth Login Button Not Appearing +Verify these settings: +```ini +[auth.generic_oauth] +enabled = true +name = AuthentiKate # This shows as the button text +``` + +#### Auto-login Not Working +Check the auto-login settings: +```ini +[auth] +oauth_auto_login = true +disable_login_form = false # Keep false to allow admin login +``` + +### Debug Mode + +Enable debug logging in Grafana: + +```ini +[log] +level = debug + +[log.console] +level = debug +``` + +Then check the Grafana logs: +```bash +docker logs grafana +``` + +### Testing OAuth Flow + +Test the OAuth endpoints manually: + +```bash +# Test AuthentiKate discovery +curl https://auth.yourdomain.com/.well-known/openid_configuration + +# Test with specific parameters +curl "https://auth.yourdomain.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https://grafana.yourdomain.com/login/generic_oauth&response_type=code&scope=openid+profile+email" +``` + +## Advanced Features + +### Custom Login Page + +Create a custom login experience: + +```ini +[auth] +disable_login_form = true +oauth_auto_login = true + +[server] +# Custom login logo +login_logo = https://yourdomain.com/logo.png +``` + +### Organization Management + +Control organization assignment: + +```ini +[users] +# Assign all OAuth users to specific org +auto_assign_org = true +auto_assign_org_id = 1 + +# Allow org admins to invite users +allow_org_create = false +``` + +### Session Management + +Configure session settings: + +```ini +[session] +# Session timeout +session_life_time = 86400 # 24 hours + +# Cookie settings +cookie_secure = true +cookie_samesite = strict +``` + +## Production Considerations + +### Security +- Use HTTPS for both AuthentiKate and Grafana +- Store client secrets securely +- Consider using environment files for secrets +- Set up proper SSL certificates + +### Performance +- Enable caching in Grafana +- Use external databases for larger installations +- Monitor authentication latency + +### Backup +- Backup Grafana configuration +- Include OAuth settings in your backup strategy +- Test authentication after restores + +Your Grafana instance is now integrated with AuthentiKate! Users can sign in with their AuthentiKate credentials and access Grafana with appropriate roles and permissions. \ No newline at end of file diff --git a/docs/integrations/nextcloud.md b/docs/integrations/nextcloud.md new file mode 100644 index 0000000..b81c2a1 --- /dev/null +++ b/docs/integrations/nextcloud.md @@ -0,0 +1,370 @@ +# Nextcloud Integration + +This guide shows how to integrate Nextcloud with AuthentiKate using the OpenID Connect app for seamless single sign-on. + +## Prerequisites + +- AuthentiKate running and accessible +- Nextcloud instance with admin access +- Nextcloud OpenID Connect app installed + +## Step 1: Install OpenID Connect App + +### Via Nextcloud App Store + +1. Log into Nextcloud as an administrator +2. Go to **Apps** → **Authentication** +3. Find and install **"OpenID Connect user backend"** +4. Enable the app + +### Via Command Line + +```bash +# Install via occ command +sudo -u www-data php occ app:install user_oidc +sudo -u www-data php occ app:enable user_oidc +``` + +## Step 2: Create Application in AuthentiKate + +1. Log into your AuthentiKate admin panel +2. Navigate to **Applications** → **Create Application** +3. Fill in the application details: + +``` +Name: Nextcloud +Redirect URI: https://cloud.yourdomain.com/apps/user_oidc/code +Icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/nextcloud.webp +``` + +4. Click **Save** and note the generated: + - **Client ID** + - **Client Secret** + +## Step 3: Configure Nextcloud OIDC + +### Via Web Interface + +1. Go to **Settings** → **Administration** → **OpenID Connect** +2. Configure the OIDC provider: + +``` +Provider Name: AuthentiKate +Identifier: authentikate +Client ID: your-client-id +Client Secret: your-client-secret +Discovery endpoint: https://auth.yourdomain.com/.well-known/openid_configuration +``` + +3. **Advanced Settings** (click to expand): +``` +Scope: openid profile email +Unique user identifier: preferred_username +``` + +4. Click **Save** + +### Via Command Line + +```bash +# Set OIDC configuration +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-clientId --value="your-client-id" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-clientSecret --value="your-client-secret" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-discoveryUrl --value="https://auth.yourdomain.com/.well-known/openid_configuration" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-scope --value="openid profile email" + +# Set unique identifier +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-uniqueUid --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-uniqueUidMapping --value="preferred_username" +``` + +## Step 4: User Attribute Mapping + +Configure how AuthentiKate user attributes map to Nextcloud: + +### Via Web Interface + +In **Settings** → **Administration** → **OpenID Connect** → **Advanced**: + +``` +Display name mapping: name +Email mapping: email +Unique user identifier: preferred_username +``` + +### Via Command Line + +```bash +# User attribute mapping +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-displayNameMapping --value="name" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-emailMapping --value="email" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-quotaMapping --value="" +``` + +## Step 5: Auto-Provisioning (Optional) + +Enable automatic user creation on first login: + +### Via Web Interface + +In the OIDC settings, enable: +- **Auto provision users** +- **Respect email verified claim** + +### Via Command Line + +```bash +# Enable auto-provisioning +sudo -u www-data php occ config:app:set user_oidc auto-provision --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-provisioningEnabled --value="1" + +# Respect email verification +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-checkEmailVerification --value="1" +``` + +## Step 6: Group Mapping (Optional) + +If you plan to add groups to AuthentiKate in the future: + +```bash +# Enable group provisioning +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-groupProvisioning --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-groupMapping --value="groups" +``` + +## Step 7: Login Button Customization + +Customize the OAuth login button: + +### Via Config + +```bash +# Set custom button text +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-buttonText --value="Login with AuthentiKate" + +# Hide default login form (optional) +sudo -u www-data php occ config:system:set hide_login_form --value=true +``` + +### Custom CSS (Optional) + +Add custom styling in **Settings** → **Administration** → **Theming**: + +```css +/* Style the OIDC login button */ +.oidc-login-button { + background-color: #3b82f6 !important; + border-color: #3b82f6 !important; +} + +.oidc-login-button:hover { + background-color: #2563eb !important; + border-color: #2563eb !important; +} +``` + +## Complete Configuration Example + +Here's a complete command-line setup: + +```bash +#!/bin/bash + +# Install and enable OIDC app +sudo -u www-data php occ app:install user_oidc +sudo -u www-data php occ app:enable user_oidc + +# Configure OIDC provider +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-clientId --value="your-client-id" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-clientSecret --value="your-client-secret" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-discoveryUrl --value="https://auth.yourdomain.com/.well-known/openid_configuration" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-scope --value="openid profile email" + +# User mapping +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-uniqueUid --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-uniqueUidMapping --value="preferred_username" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-displayNameMapping --value="name" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-emailMapping --value="email" + +# Auto-provisioning +sudo -u www-data php occ config:app:set user_oidc auto-provision --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-provisioningEnabled --value="1" +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-checkEmailVerification --value="1" + +# Button customization +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-buttonText --value="Login with AuthentiKate" + +echo "Nextcloud OIDC integration configured successfully!" +``` + +## Docker Compose Example + +Complete Docker setup with Nextcloud and AuthentiKate: + +```yaml +version: '3.8' + +services: + nextcloud: + image: nextcloud:latest + container_name: nextcloud + restart: unless-stopped + ports: + - "80:80" + environment: + - NEXTCLOUD_ADMIN_USER=admin + - NEXTCLOUD_ADMIN_PASSWORD=secure_password + - NEXTCLOUD_TRUSTED_DOMAINS=cloud.yourdomain.com + - OVERWRITEPROTOCOL=https + - OVERWRITEHOST=cloud.yourdomain.com + volumes: + - nextcloud_data:/var/www/html + - ./setup-oidc.sh:/docker-entrypoint-hooks.d/pre-installation/setup-oidc.sh:ro + labels: + # Traefik labels + - "traefik.enable=true" + - "traefik.http.routers.nextcloud.rule=Host(`cloud.yourdomain.com`)" + - "traefik.http.routers.nextcloud.entrypoints=websecure" + - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt" + +volumes: + nextcloud_data: +``` + +## Testing the Integration + +1. **Log out** of Nextcloud (if currently logged in) +2. **Navigate to** your Nextcloud login page +3. **Click "Login with AuthentiKate"** button +4. **Authenticate** with your AuthentiKate credentials +5. **Verify** you're logged into Nextcloud with correct user information + +## Advanced Configuration + +### Custom User Provisioning + +Control how users are created: + +```bash +# Set default quota for new users +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-defaultQuota --value="5GB" + +# Set default group for new users +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-defaultGroup --value="users" +``` + +### Backup Users + +Prevent deletion of users not found in OIDC: + +```bash +# Enable soft delete (backup users) +sudo -u www-data php occ config:app:set user_oidc provider-authentikate-softAutoUpdate --value="1" +``` + +### Admin Users + +Make specific users administrators: + +```bash +# Add users to admin group (run after first login) +sudo -u www-data php occ group:adduser admin "admin_username" +``` + +## Troubleshooting + +### Common Issues + +#### "Invalid redirect URI" Error +Ensure the redirect URI in AuthentiKate exactly matches: +``` +https://cloud.yourdomain.com/apps/user_oidc/code +``` + +#### OIDC Login Button Missing +Check that the app is enabled: +```bash +sudo -u www-data php occ app:list | grep user_oidc +``` + +#### Users Not Auto-Created +Verify auto-provisioning is enabled: +```bash +sudo -u www-data php occ config:app:get user_oidc auto-provision +sudo -u www-data php occ config:app:get user_oidc provider-authentikate-provisioningEnabled +``` + +#### Wrong User Information +Check the attribute mapping: +```bash +sudo -u www-data php occ config:app:get user_oidc provider-authentikate-displayNameMapping +sudo -u www-data php occ config:app:get user_oidc provider-authentikate-emailMapping +``` + +### Debug Mode + +Enable debugging in Nextcloud: + +```bash +# Enable debug mode +sudo -u www-data php occ config:system:set debug --value=true + +# Check logs +sudo -u www-data php occ log:tail +``` + +### Configuration Check + +Verify your OIDC configuration: + +```bash +# List all OIDC settings +sudo -u www-data php occ config:list user_oidc + +# Test OIDC discovery endpoint +curl https://auth.yourdomain.com/.well-known/openid_configuration +``` + +### Reset Configuration + +If you need to start over: + +```bash +# Remove OIDC configuration +sudo -u www-data php occ config:app:delete user_oidc provider-authentikate-clientId +sudo -u www-data php occ config:app:delete user_oidc provider-authentikate-clientSecret +sudo -u www-data php occ config:app:delete user_oidc provider-authentikate-discoveryUrl + +# Disable auto-provisioning +sudo -u www-data php occ config:app:set user_oidc auto-provision --value="0" +``` + +## Security Considerations + +### Trusted Domains + +Ensure your domain is in Nextcloud's trusted domains: + +```bash +sudo -u www-data php occ config:system:set trusted_domains 0 --value="cloud.yourdomain.com" +``` + +### HTTPS Configuration + +Force HTTPS in Nextcloud: + +```bash +sudo -u www-data php occ config:system:set overwriteprotocol --value="https" +sudo -u www-data php occ config:system:set overwrite.cli.url --value="https://cloud.yourdomain.com" +``` + +### Session Security + +Configure secure sessions: + +```bash +sudo -u www-data php occ config:system:set session_lifetime --value=3600 +sudo -u www-data php occ config:system:set session_keepalive --value=false +``` + +Your Nextcloud instance is now integrated with AuthentiKate! Users can sign in with their AuthentiKate credentials and access their Nextcloud files and applications. \ No newline at end of file diff --git a/docs/integrations/overview.md b/docs/integrations/overview.md new file mode 100644 index 0000000..fe61d32 --- /dev/null +++ b/docs/integrations/overview.md @@ -0,0 +1,324 @@ +# Integration Overview + +AuthentiKate supports OpenID Connect (OIDC) and OAuth 2.0, making it compatible with hundreds of applications. This section covers how to integrate AuthentiKate with popular homelab applications. + +## OIDC Endpoints + +All applications will need these AuthentiKate endpoints: + +| Endpoint | URL | Description | +|----------|-----|-------------| +| **Discovery** | `/.well-known/openid_configuration` | Auto-configuration endpoint | +| **Authorization** | `/oauth/authorize` | User authorization endpoint | +| **Token** | `/oauth/token` | Token exchange endpoint | +| **User Info** | `/oauth/userinfo` | User profile endpoint | +| **JWKS** | `/.well-known/jwks.json` | JSON Web Key Set | + +::: tip +Most modern applications can auto-configure using just the discovery endpoint. Use `https://auth.yourdomain.com/.well-known/openid_configuration` when possible. +::: + +## Quick Integration Steps + +### 1. Create Application in AuthentiKate + +1. Log into AuthentiKate admin panel +2. Go to **Applications** → **Create Application** +3. Fill in the details: + - **Name**: Your application name + - **Redirect URI**: Your app's OAuth callback URL + - **Icon**: Optional icon URL + +4. Save and note the **Client ID** and **Client Secret** + +### 2. Configure Your Application + +Use the generated credentials in your application's OAuth/OIDC settings: + +- **Provider URL**: `https://auth.yourdomain.com` +- **Client ID**: (from step 1) +- **Client Secret**: (from step 1) +- **Scopes**: `openid profile email` + +### 3. Test the Integration + +1. Try logging into your application +2. You should be redirected to AuthentiKate +3. After authentication, you'll be returned to your app + +## Supported Applications + +### Ready-to-Use Guides + +- [**Grafana**](/integrations/grafana) - Analytics and monitoring +- [**Nextcloud**](/integrations/nextcloud) - File sharing and collaboration +- [**Traefik Forward Auth**](/integrations/traefik) - Reverse proxy authentication + +### Compatible Applications + +AuthentiKate works with any application that supports OIDC/OAuth2: + +#### **Monitoring & Analytics** +- Grafana ✅ +- Prometheus +- Uptime Kuma +- Tautulli +- Zabbix +- LibreNMS + +#### **Media & Entertainment** +- Jellyfin +- Plex (via Tautulli) +- Overseerr +- Sonarr/Radarr/Lidarr +- Ombi + +#### **Productivity & Files** +- Nextcloud ✅ +- BookStack +- Paperless-ngx +- Standard Notes +- Joplin Server +- PhotoPrism +- Immich + +#### **Development & Git** +- Gitea +- GitLab +- Forgejo +- Drone CI +- Jenkins + +#### **Communication** +- Mattermost +- Rocket.Chat +- Element (Matrix) + +#### **Infrastructure & Networking** +- Portainer +- Proxmox +- pfSense +- OPNsense +- Traefik ✅ + +#### **Finance & Business** +- Firefly III +- Invoice Ninja +- Crater +- Akaunting + +## Application Templates + +AuthentiKate includes templates for popular applications: + +```javascript +// Example: Grafana template +{ + name: "Grafana", + redirectUri: "https://grafana.yourdomain.com/login/generic_oauth", + icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/grafana.webp" +} +``` + +Available templates: +- Grafana +- Nextcloud +- Proxmox +- Portainer +- GitLab +- And many more... + +## Integration Patterns + +### Pattern 1: Direct OIDC Integration + +Best for applications with built-in OIDC support: + +```mermaid +graph LR + A[User] --> B[Application] + B --> C[AuthentiKate] + C --> B + B --> A +``` + +**Examples**: Grafana, Nextcloud, GitLab + +### Pattern 2: Reverse Proxy Authentication + +For applications without OIDC support: + +```mermaid +graph LR + A[User] --> B[Reverse Proxy] + B --> C[AuthentiKate] + C --> B + B --> D[Application] + D --> B + B --> A +``` + +**Examples**: Traefik Forward Auth, nginx auth_request + +### Pattern 3: Header-Based Authentication + +Applications that accept authentication headers: + +```mermaid +graph LR + A[User] --> B[Proxy + Headers] + B --> C[AuthentiKate] + C --> B + B --> D[Application] +``` + +**Examples**: Proxmox, Portainer (with middleware) + +## Common Configuration Values + +Most applications need these standard values: + +### Basic OIDC Settings +```yaml +provider_url: https://auth.yourdomain.com +client_id: your-client-id +client_secret: your-client-secret +scopes: openid profile email +``` + +### Advanced Settings +```yaml +# Token validation +jwks_uri: https://auth.yourdomain.com/.well-known/jwks.json +issuer: https://auth.yourdomain.com + +# User mapping +username_claim: preferred_username +email_claim: email +name_claim: name + +# Security +require_https: true +verify_ssl: true +``` + +## User Attribute Mapping + +AuthentiKate provides these user claims: + +| Claim | Description | Example | +|-------|-------------|---------| +| `sub` | Unique user ID (UUID) | `f47ac10b-58cc-4372-a567-0e02b2c3d479` | +| `email` | User email address | `user@example.com` | +| `name` | Full display name | `John Doe` | +| `preferred_username` | Username | `john.doe` | +| `email_verified` | Email verification status | `true` | +| `picture` | Avatar URL | `https://auth.yourdomain.com/storage/avatars/...` | + +### Custom User Mapping + +Some applications need custom field mapping: + +```yaml +# Grafana example +field_mapping: + login: preferred_username + email: email + name: name + +# GitLab example +user_info_mapping: + username: preferred_username + email: email + name: name +``` + +## Troubleshooting Common Issues + +### Invalid Redirect URI +``` +Error: Invalid redirect URI +``` + +**Solution**: Ensure the redirect URI in AuthentiKate exactly matches your application's callback URL. + +### Invalid Client +``` +Error: Invalid client credentials +``` + +**Solution**: Double-check the Client ID and Client Secret in your application settings. + +### SSL/HTTPS Issues +``` +Error: SSL verification failed +``` + +**Solutions**: +- Ensure AuthentiKate is accessible via HTTPS +- Use valid SSL certificates +- Set `verify_ssl: false` only for testing + +### Token Validation Errors +``` +Error: Invalid token signature +``` + +**Solution**: Verify the JWKS endpoint is accessible and your application is using the correct validation method. + +## Testing Your Integration + +### 1. Manual Testing +1. Try logging into your application +2. Check that you're redirected to AuthentiKate +3. Verify successful authentication returns you to the app +4. Confirm user details are populated correctly + +### 2. Token Validation +```bash +# Test the discovery endpoint +curl https://auth.yourdomain.com/.well-known/openid_configuration + +# Test JWKS endpoint +curl https://auth.yourdomain.com/.well-known/jwks.json + +# Test user info (requires valid token) +curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ + https://auth.yourdomain.com/oauth/userinfo +``` + +### 3. Debug Mode +Enable debug logging in your application to see: +- OAuth request/response details +- Token validation steps +- User claim mapping + +## Security Best Practices + +### Client Configuration +- Use strong, unique Client Secrets +- Implement proper redirect URI validation +- Use HTTPS for all communication +- Validate SSL certificates + +### Scope Management +- Request minimal necessary scopes +- Use `openid` scope for OIDC compliance +- Add `profile` and `email` as needed + +### Token Handling +- Store tokens securely +- Implement proper token refresh +- Validate token signatures +- Respect token expiration + +## Getting Help + +If you're having trouble integrating an application: + +1. **Check the logs**: Both AuthentiKate and your application logs +2. **Verify endpoints**: Test OIDC endpoints with curl +3. **Compare settings**: Use working examples as reference +4. **Community help**: Check GitHub discussions for similar integrations + +Ready to integrate your first application? Start with our [Grafana guide](/integrations/grafana) for a step-by-step walkthrough. \ No newline at end of file diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..be92f74 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "devDependencies": { + "vitepress": "^1.6.3" + } +} \ No newline at end of file diff --git a/package.json b/package.json index aeb9543..68c3006 100644 --- a/package.json +++ b/package.json @@ -19,4 +19,4 @@ "@tailwindcss/oxide-linux-x64-gnu": "^4.0.1", "lightningcss-linux-x64-gnu": "^1.29.1" } -} +} \ No newline at end of file