From 14c2334e1b259fddd35b2de16eb877246b4a0717 Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:46:21 +0200 Subject: [PATCH 1/6] fix(defender): change policies rules key (#8702) --- prowler/CHANGELOG.md | 5 +-- .../services/defender/defender_service.py | 34 +++++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index ac48ae2a1e..9df610cdd9 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -7,17 +7,18 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - Support for AdditionalURLs in outputs [(#8651)](https://github.com/prowler-cloud/prowler/pull/8651) - Support for markdown metadata fields in Dashboard [(#8667)](https://github.com/prowler-cloud/prowler/pull/8667) -### Changed -- Update AWS Neptune service metadata to new format [(#8494)](https://github.com/prowler-cloud/prowler/pull/8494) ### Changed +- Update AWS Neptune service metadata to new format [(#8494)](https://github.com/prowler-cloud/prowler/pull/8494) - Update AWS Config service metadata to new format [(#8641)](https://github.com/prowler-cloud/prowler/pull/8641) + ### Fixed ## [v5.12.1] (Prowler v5.12.1) ### Fixed - Replaced old check id with new ones for compliance files [(#8682)](https://github.com/prowler-cloud/prowler/pull/8682) +- Replace defender rules policies key to use old name [(#8702)](https://github.com/prowler-cloud/prowler/pull/8702) ## [v5.12.0] (Prowler v5.12.0) diff --git a/prowler/providers/m365/services/defender/defender_service.py b/prowler/providers/m365/services/defender/defender_service.py index 5d198b5888..d3ede5734a 100644 --- a/prowler/providers/m365/services/defender/defender_service.py +++ b/prowler/providers/m365/services/defender/defender_service.py @@ -91,7 +91,7 @@ class Defender(M365Service): malware_rule = [malware_rule] for rule in malware_rule: if rule: - malware_rules[rule.get("Name", "")] = MalwareRule( + malware_rules[rule.get("MalwareFilterPolicy", "")] = MalwareRule( state=rule.get("State", ""), priority=rule.get("Priority", 0), users=rule.get("SentTo", None), @@ -152,12 +152,14 @@ class Defender(M365Service): antiphishing_rule = [antiphishing_rule] for rule in antiphishing_rule: if rule: - antiphishing_rules[rule.get("Name", "")] = AntiphishingRule( - state=rule.get("State", ""), - priority=rule.get("Priority", 0), - users=rule.get("SentTo", None), - groups=rule.get("SentToMemberOf", None), - domains=rule.get("RecipientDomainIs", None), + antiphishing_rules[rule.get("AntiPhishPolicy", "")] = ( + AntiphishingRule( + state=rule.get("State", ""), + priority=rule.get("Priority", 0), + users=rule.get("SentTo", None), + groups=rule.get("SentToMemberOf", None), + domains=rule.get("RecipientDomainIs", None), + ) ) except Exception as error: logger.error( @@ -250,7 +252,9 @@ class Defender(M365Service): outbound_spam_rule = [outbound_spam_rule] for rule in outbound_spam_rule: if rule: - outbound_spam_rules[rule.get("Name", "")] = OutboundSpamRule( + outbound_spam_rules[ + rule.get("HostedOutboundSpamFilterPolicy", "") + ] = OutboundSpamRule( state=rule.get("State", "Disabled"), priority=rule.get("Priority", 0), users=rule.get("From", None), @@ -330,12 +334,14 @@ class Defender(M365Service): inbound_spam_rule = [inbound_spam_rule] for rule in inbound_spam_rule: if rule: - inbound_spam_rules[rule.get("Name", "")] = InboundSpamRule( - state=rule.get("State", "Disabled"), - priority=rule.get("Priority", 0), - users=rule.get("SentTo", None), - groups=rule.get("SentToMemberOf", None), - domains=rule.get("RecipientDomainIs", None), + inbound_spam_rules[rule.get("HostedContentFilterPolicy", "")] = ( + InboundSpamRule( + state=rule.get("State", "Disabled"), + priority=rule.get("Priority", 0), + users=rule.get("SentTo", None), + groups=rule.get("SentToMemberOf", None), + domains=rule.get("RecipientDomainIs", None), + ) ) except Exception as error: logger.error( From 82cd29d5958287a440ccbd0d64934238381772bc Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:02:36 +0200 Subject: [PATCH 2/6] fix(auth): add method attribute to form for proper submission handling (#8699) --- ui/CHANGELOG.md | 4 ++++ ui/components/auth/oss/auth-form.tsx | 1 + 2 files changed, 5 insertions(+) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 582cec2700..8a3245b1ac 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -9,6 +9,10 @@ All notable changes to the **Prowler UI** are documented in this file. - `Prowler Hub` menu item with tooltip [(#8692)] (https://github.com/prowler-cloud/prowler/pull/8692) - Copy link button to finding detail page [(#8685)] (https://github.com/prowler-cloud/prowler/pull/8685) +### 🐞 Fixed + +- POST method on auth form [(#8699)] (https://github.com/prowler-cloud/prowler/pull/8699) + ## [1.12.0] (Prowler v5.12.0) ### 🚀 Added diff --git a/ui/components/auth/oss/auth-form.tsx b/ui/components/auth/oss/auth-form.tsx index 15c84b4350..d5f30f0836 100644 --- a/ui/components/auth/oss/auth-form.tsx +++ b/ui/components/auth/oss/auth-form.tsx @@ -206,6 +206,7 @@ export const AuthForm = ({
From 6f967c6da7c077dd2dc3752ec55be426e5e1b178 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:29:49 +0200 Subject: [PATCH 3/6] fix(auth): validate email field (#8698) --- ui/CHANGELOG.md | 1 + ui/actions/auth/auth.ts | 2 +- ui/components/auth/oss/auth-form.tsx | 30 +++++++++++++--------------- ui/tests/auth-login.spec.ts | 10 ++++------ ui/tests/helpers.ts | 4 +++- ui/types/authFormSchema.ts | 7 ++++++- 6 files changed, 29 insertions(+), 25 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 8a3245b1ac..6b599c24ed 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🐞 Fixed +- Field-level email validation message [(#8698)] (https://github.com/prowler-cloud/prowler/pull/8698) - POST method on auth form [(#8699)] (https://github.com/prowler-cloud/prowler/pull/8699) ## [1.12.0] (Prowler v5.12.0) diff --git a/ui/actions/auth/auth.ts b/ui/actions/auth/auth.ts index fe93e03f04..5d478ff5ba 100644 --- a/ui/actions/auth/auth.ts +++ b/ui/actions/auth/auth.ts @@ -35,7 +35,7 @@ export async function authenticate( message: "Credentials error", errors: { ...defaultValues, - credentials: "Incorrect email or password", + credentials: "Invalid email or password", }, }; case "CallbackRouteError": diff --git a/ui/components/auth/oss/auth-form.tsx b/ui/components/auth/oss/auth-form.tsx index d5f30f0836..7e11d7cf9c 100644 --- a/ui/components/auth/oss/auth-form.tsx +++ b/ui/components/auth/oss/auth-form.tsx @@ -12,7 +12,7 @@ import { authenticate, createNewUser } from "@/actions/auth"; import { initiateSamlAuth } from "@/actions/integrations/saml"; import { PasswordRequirementsMessage } from "@/components/auth/oss/password-validator"; import { SocialButtons } from "@/components/auth/oss/social-buttons"; -import { NotificationIcon, ProwlerExtended } from "@/components/icons"; +import { ProwlerExtended } from "@/components/icons"; import { ThemeSwitch } from "@/components/ThemeSwitch"; import { useToast } from "@/components/ui"; import { CustomButton, CustomInput } from "@/components/ui/custom"; @@ -65,6 +65,8 @@ export const AuthForm = ({ const form = useForm>({ resolver: zodResolver(formSchema), + mode: "onSubmit", + reValidateMode: "onSubmit", defaultValues: { email: "", password: "", @@ -111,10 +113,11 @@ export const AuthForm = ({ if (result?.message === "Success") { router.push("/"); } else if (result?.errors && "credentials" in result.errors) { - form.setError("email", { - type: "server", - message: result.errors.credentials ?? "Incorrect email or password", - }); + const message = + result.errors.credentials ?? "Invalid email or password"; + + form.setError("email", { type: "server", message }); + form.setError("password", { type: "server", message }); } else if (result?.message === "User email is not verified") { router.push("/email-verification"); } else { @@ -206,6 +209,7 @@ export const AuthForm = ({ {!isSamlMode && ( <> @@ -246,10 +251,8 @@ export const AuthForm = ({ control={form.control} name="password" password - isInvalid={ - !!form.formState.errors.password || - !!form.formState.errors.email - } + // Only mark invalid when the password field has an error + isInvalid={!!form.formState.errors.password} /> {type === "sign-up" && ( )} - {type === "sign-in" && form.formState.errors?.email && ( -
- -

Invalid email or password

-
- )} + { test("should handle empty form submission", async ({ page }) => { // Submit empty form await submitLoginForm(page); - await verifyLoginError(page, ERROR_MESSAGES.INVALID_CREDENTIALS); + await verifyLoginError(page, ERROR_MESSAGES.INVALID_EMAIL); + // Verify we're still on login page await expect(page).toHaveURL(URLS.LOGIN); }); - /* - TODO: This test is failing, need UI work before. test("should validate email format", async ({ page }) => { // Attempt login with invalid email format await login(page, TEST_CREDENTIALS.INVALID_EMAIL_FORMAT); - // Verify error message (application shows generic error for invalid email format too) - await verifyLoginError(page, ERROR_MESSAGES.INVALID_CREDENTIALS); + // Verify field-level email validation message + await verifyLoginError(page, ERROR_MESSAGES.INVALID_EMAIL); // Verify we're still on login page await expect(page).toHaveURL(URLS.LOGIN); }); - */ test("should toggle SAML SSO mode", async ({ page }) => { // Toggle to SAML mode diff --git a/ui/tests/helpers.ts b/ui/tests/helpers.ts index cb2e8d2857..22c45b4ba5 100644 --- a/ui/tests/helpers.ts +++ b/ui/tests/helpers.ts @@ -2,6 +2,7 @@ import { Page, expect } from "@playwright/test"; export const ERROR_MESSAGES = { INVALID_CREDENTIALS: "Invalid email or password", + INVALID_EMAIL: "Please enter a valid email address.", } as const; export const URLS = { @@ -69,7 +70,8 @@ export async function verifyLoginError( page: Page, errorMessage = "Invalid email or password", ) { - await expect(page.getByText(errorMessage)).toBeVisible(); + // There may be multiple field-level errors with the same text; assert at least one is visible + await expect(page.getByText(errorMessage).first()).toBeVisible(); await expect(page).toHaveURL("/sign-in"); } diff --git a/ui/types/authFormSchema.ts b/ui/types/authFormSchema.ts index b4600e6cbf..d16c027790 100644 --- a/ui/types/authFormSchema.ts +++ b/ui/types/authFormSchema.ts @@ -96,7 +96,12 @@ export const authFormSchema = (type: string) => }), // Fields for Sign In and Sign Up - email: z.string().email(), + // Trim and normalize email, and provide consistent message + email: z + .string() + .trim() + .toLowerCase() + .email({ message: "Please enter a valid email address." }), password: type === "sign-in" ? z.string() : validatePassword(), isSamlMode: z.boolean().optional(), }) From c4a877164764ecb169e268b546a29c5bfd843650 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:36:06 +0200 Subject: [PATCH 4/6] chore(dependencies): update package versions and track them (#8696) --- ui/.npmrc | 1 + ui/dependency-log.json | 634 ++++++ ui/hooks/use-sidebar.ts | 9 - ui/package-lock.json | 3205 +++++++++++++++++++++------ ui/package.json | 174 +- ui/scripts/update-dependency-log.js | 95 + 6 files changed, 3402 insertions(+), 716 deletions(-) create mode 100644 ui/dependency-log.json create mode 100644 ui/scripts/update-dependency-log.js diff --git a/ui/.npmrc b/ui/.npmrc index cafe685a11..dc8b06aad2 100644 --- a/ui/.npmrc +++ b/ui/.npmrc @@ -1 +1,2 @@ package-lock=true +save-exact=true diff --git a/ui/dependency-log.json b/ui/dependency-log.json new file mode 100644 index 0000000000..59b09f2199 --- /dev/null +++ b/ui/dependency-log.json @@ -0,0 +1,634 @@ +[ + { + "section": "dependencies", + "name": "@hookform/resolvers", + "from": "3.10.0", + "to": "3.10.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@langchain/langgraph-supervisor", + "from": "0.0.12", + "to": "0.0.12", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@langchain/openai", + "from": "0.6.9", + "to": "0.6.9", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@next/third-parties", + "from": "15.3.5", + "to": "15.3.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@nextui-org/react", + "from": "2.4.8", + "to": "2.4.8", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@nextui-org/system", + "from": "2.2.1", + "to": "2.2.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@nextui-org/theme", + "from": "2.2.5", + "to": "2.2.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-alert-dialog", + "from": "1.1.14", + "to": "1.1.14", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-dialog", + "from": "1.1.14", + "to": "1.1.14", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-dropdown-menu", + "from": "2.1.15", + "to": "2.1.15", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-icons", + "from": "1.3.2", + "to": "1.3.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-label", + "from": "2.1.7", + "to": "2.1.7", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-select", + "from": "2.2.5", + "to": "2.2.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-slot", + "from": "1.2.3", + "to": "1.2.3", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@radix-ui/react-toast", + "from": "1.2.14", + "to": "1.2.14", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@react-aria/ssr", + "from": "3.9.4", + "to": "3.9.4", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@react-aria/visually-hidden", + "from": "3.8.12", + "to": "3.8.12", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@tailwindcss/typography", + "from": "0.5.16", + "to": "0.5.16", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@tanstack/react-table", + "from": "8.21.3", + "to": "8.21.3", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "@types/js-yaml", + "from": "4.0.9", + "to": "4.0.9", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "ai", + "from": "4.3.16", + "to": "4.3.16", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "alert", + "from": "6.0.2", + "to": "6.0.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "class-variance-authority", + "from": "0.7.1", + "to": "0.7.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "clsx", + "from": "2.1.1", + "to": "2.1.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "date-fns", + "from": "4.1.0", + "to": "4.1.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "framer-motion", + "from": "11.18.2", + "to": "11.18.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "intl-messageformat", + "from": "10.7.16", + "to": "10.7.16", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "jose", + "from": "5.10.0", + "to": "5.10.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "js-yaml", + "from": "4.1.0", + "to": "4.1.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "jwt-decode", + "from": "4.0.0", + "to": "4.0.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "lucide-react", + "from": "0.543.0", + "to": "0.543.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "marked", + "from": "15.0.12", + "to": "15.0.12", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "next", + "from": "14.2.32", + "to": "14.2.32", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "next-auth", + "from": "5.0.0-beta.29", + "to": "5.0.0-beta.29", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "next-themes", + "from": "0.2.1", + "to": "0.2.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "radix-ui", + "from": "1.4.2", + "to": "1.4.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "react", + "from": "18.3.1", + "to": "18.3.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "react-dom", + "from": "18.3.1", + "to": "18.3.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "react-hook-form", + "from": "7.62.0", + "to": "7.62.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "react-markdown", + "from": "10.1.0", + "to": "10.1.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "recharts", + "from": "2.15.4", + "to": "2.15.4", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "rss-parser", + "from": "3.13.0", + "to": "3.13.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "server-only", + "from": "0.0.1", + "to": "0.0.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "shadcn", + "from": "3.2.1", + "to": "3.2.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "sharp", + "from": "0.33.5", + "to": "0.33.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "tailwind-merge", + "from": "3.3.1", + "to": "3.3.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "tailwindcss-animate", + "from": "1.0.7", + "to": "1.0.7", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "uuid", + "from": "11.1.0", + "to": "11.1.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "zod", + "from": "3.25.73", + "to": "3.25.73", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "dependencies", + "name": "zustand", + "from": "4.5.7", + "to": "4.5.7", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.548Z" + }, + { + "section": "devDependencies", + "name": "@iconify/react", + "from": "5.2.1", + "to": "5.2.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@playwright/test", + "from": "1.53.2", + "to": "1.53.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@types/node", + "from": "20.5.7", + "to": "20.5.7", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@types/react", + "from": "18.3.3", + "to": "18.3.3", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@types/react-dom", + "from": "18.3.0", + "to": "18.3.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@types/uuid", + "from": "10.0.0", + "to": "10.0.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@typescript-eslint/eslint-plugin", + "from": "7.18.0", + "to": "7.18.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "@typescript-eslint/parser", + "from": "7.18.0", + "to": "7.18.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "autoprefixer", + "from": "10.4.19", + "to": "10.4.19", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint", + "from": "8.57.1", + "to": "8.57.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-config-next", + "from": "14.2.32", + "to": "14.2.32", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-config-prettier", + "from": "10.1.5", + "to": "10.1.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-import", + "from": "2.32.0", + "to": "2.32.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-jsx-a11y", + "from": "6.10.2", + "to": "6.10.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-node", + "from": "11.1.0", + "to": "11.1.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-prettier", + "from": "5.5.1", + "to": "5.5.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-react", + "from": "7.37.5", + "to": "7.37.5", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-react-hooks", + "from": "4.6.2", + "to": "4.6.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-security", + "from": "3.0.1", + "to": "3.0.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-simple-import-sort", + "from": "12.1.1", + "to": "12.1.1", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "eslint-plugin-unused-imports", + "from": "3.2.0", + "to": "3.2.0", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "husky", + "from": "9.1.7", + "to": "9.1.7", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "lint-staged", + "from": "15.5.2", + "to": "15.5.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "postcss", + "from": "8.4.38", + "to": "8.4.38", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "prettier", + "from": "3.6.2", + "to": "3.6.2", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "prettier-plugin-tailwindcss", + "from": "0.6.13", + "to": "0.6.13", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "tailwind-variants", + "from": "0.1.20", + "to": "0.1.20", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "tailwindcss", + "from": "3.4.3", + "to": "3.4.3", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + }, + { + "section": "devDependencies", + "name": "typescript", + "from": "5.5.4", + "to": "5.5.4", + "strategy": "installed", + "generatedAt": "2025-09-10T11:50:17.554Z" + } +] diff --git a/ui/hooks/use-sidebar.ts b/ui/hooks/use-sidebar.ts index feaf5af9f2..f2fe831170 100644 --- a/ui/hooks/use-sidebar.ts +++ b/ui/hooks/use-sidebar.ts @@ -1,4 +1,3 @@ -import { produce } from "immer"; import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; @@ -11,7 +10,6 @@ type SidebarStore = { setIsOpen: (isOpen: boolean) => void; setIsHover: (isHover: boolean) => void; getOpenState: () => boolean; - setSettings: (settings: Partial) => void; }; export const useSidebar = create( @@ -33,13 +31,6 @@ export const useSidebar = create( const state = get(); return state.isOpen || (state.settings.isHoverOpen && state.isHover); }, - setSettings: (settings: Partial) => { - set( - produce((state: SidebarStore) => { - state.settings = { ...state.settings, ...settings }; - }), - ); - }, }), { name: "sidebar", diff --git a/ui/package-lock.json b/ui/package-lock.json index 984c9a0895..97bd9a4c12 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -7,94 +7,89 @@ "": { "name": "prowler-next-app", "version": "0.0.1", + "hasInstallScript": true, "dependencies": { - "@hookform/resolvers": "^3.9.0", - "@langchain/langgraph-supervisor": "^0.0.12", - "@langchain/openai": "^0.6.9", - "@next/third-parties": "^15.3.3", + "@hookform/resolvers": "3.10.0", + "@langchain/langgraph-supervisor": "0.0.12", + "@langchain/openai": "0.6.9", + "@next/third-parties": "15.3.5", "@nextui-org/react": "2.4.8", "@nextui-org/system": "2.2.1", "@nextui-org/theme": "2.2.5", - "@radix-ui/react-alert-dialog": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-slot": "^1.1.1", - "@radix-ui/react-toast": "^1.2.4", + "@radix-ui/react-alert-dialog": "1.1.14", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-dropdown-menu": "2.1.15", + "@radix-ui/react-icons": "1.3.2", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-toast": "1.2.14", "@react-aria/ssr": "3.9.4", "@react-aria/visually-hidden": "3.8.12", - "@tailwindcss/typography": "^0.5.16", - "@tanstack/react-table": "^8.19.3", - "@types/js-yaml": "^4.0.9", - "add": "^2.0.6", - "ai": "^4.3.16", - "alert": "^6.0.2", - "bcryptjs": "^2.4.3", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "cmdk": "^1.0.0", - "date-fns": "^4.1.0", - "framer-motion": "^11.16.0", - "immer": "^10.1.1", - "intl-messageformat": "^10.5.0", - "jose": "^5.9.3", - "js-yaml": "^4.1.0", - "jwt-decode": "^4.0.0", - "lucide-react": "^0.471.0", - "marked": "^15.0.12", - "next": "^14.2.32", - "next-auth": "^5.0.0-beta.25", - "next-themes": "^0.2.1", - "radix-ui": "^1.1.3", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-hook-form": "^7.52.2", - "react-markdown": "^10.1.0", - "recharts": "^2.15.2", - "rss-parser": "^3.13.0", - "server-only": "^0.0.1", - "shadcn-ui": "^0.2.3", - "sharp": "^0.33.5", - "tailwind-merge": "^3.2.0", - "tailwindcss-animate": "^1.0.7", - "uuid": "^11.0.5", - "zod": "^3.23.8", - "zustand": "^4.5.5" + "@tailwindcss/typography": "0.5.16", + "@tanstack/react-table": "8.21.3", + "@types/js-yaml": "4.0.9", + "ai": "4.3.16", + "alert": "6.0.2", + "class-variance-authority": "0.7.1", + "clsx": "2.1.1", + "date-fns": "4.1.0", + "framer-motion": "11.18.2", + "intl-messageformat": "10.7.16", + "jose": "5.10.0", + "js-yaml": "4.1.0", + "jwt-decode": "4.0.0", + "lucide-react": "0.543.0", + "marked": "15.0.12", + "next": "14.2.32", + "next-auth": "5.0.0-beta.29", + "next-themes": "0.2.1", + "radix-ui": "1.4.2", + "react": "18.3.1", + "react-dom": "18.3.1", + "react-hook-form": "7.62.0", + "react-markdown": "10.1.0", + "recharts": "2.15.4", + "rss-parser": "3.13.0", + "server-only": "0.0.1", + "shadcn": "3.2.1", + "sharp": "0.33.5", + "tailwind-merge": "3.3.1", + "tailwindcss-animate": "1.0.7", + "uuid": "11.1.0", + "zod": "3.25.73", + "zustand": "4.5.7" }, "devDependencies": { - "@iconify/react": "^5.2.0", - "@playwright/test": "^1.53.1", - "@types/bcryptjs": "^2.4.6", + "@iconify/react": "5.2.1", + "@playwright/test": "1.53.2", "@types/node": "20.5.7", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", - "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", + "@types/uuid": "10.0.0", + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.18.0", "autoprefixer": "10.4.19", - "eslint": "^8.56.0", - "eslint-config-next": "^14.2.32", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.23.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-security": "^3.0.1", - "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^3.2.0", - "husky": "^9.0.11", - "lint-staged": "^15.2.7", + "eslint": "8.57.1", + "eslint-config-next": "14.2.32", + "eslint-config-prettier": "10.1.5", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-jsx-a11y": "6.10.2", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-prettier": "5.5.1", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-security": "3.0.1", + "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-unused-imports": "3.2.0", + "husky": "9.1.7", + "lint-staged": "15.5.2", "postcss": "8.4.38", - "prettier": "^3.3.3", - "prettier-plugin-tailwindcss": "^0.6.8", + "prettier": "3.6.2", + "prettier-plugin-tailwindcss": "0.6.13", "tailwind-variants": "0.1.20", "tailwindcss": "3.4.3", - "typescript": "5.5.4", - "usehooks-ts": "^3.1.0" + "typescript": "5.5.4" } }, "node_modules/@ai-sdk/provider": { @@ -179,21 +174,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@antfu/ni": { - "version": "0.21.12", - "resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-0.21.12.tgz", - "integrity": "sha512-2aDL3WUv8hMJb2L3r/PIQWsTLyq7RQr3v9xD16fiz6O8ys1xEyLhhTOv8gxtZvJiTzjTF5pHoArvRdesGL1DMQ==", - "license": "MIT", - "bin": { - "na": "bin/na.mjs", - "nci": "bin/nci.mjs", - "ni": "bin/ni.mjs", - "nlx": "bin/nlx.mjs", - "nr": "bin/nr.mjs", - "nu": "bin/nu.mjs", - "nun": "bin/nun.mjs" - } - }, "node_modules/@auth/core": { "version": "0.40.0", "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.40.0.tgz", @@ -246,6 +226,270 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", @@ -255,6 +499,77 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", @@ -264,6 +579,69 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "license": "ISC", + "dependencies": { + "cookie": "^0.7.2" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "license": "ISC", + "dependencies": { + "statuses": "^2.0.1" + } + }, "node_modules/@cfworker/json-schema": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", @@ -271,6 +649,212 @@ "license": "MIT", "peer": true }, + "node_modules/@dotenvx/dotenvx": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.49.0.tgz", + "integrity": "sha512-M1cyP6YstFQCjih54SAxCqHLMMi8QqV8tenpgGE48RTXWD7vfMYJiw/6xcCDpS2h28AcLpTsFCZA863Ge9yxzA==", + "license": "BSD-3-Clause", + "dependencies": { + "commander": "^11.1.0", + "dotenv": "^17.2.1", + "eciesjs": "^0.4.10", + "execa": "^5.1.1", + "fdir": "^6.2.0", + "ignore": "^5.3.0", + "object-treeify": "1.1.33", + "picomatch": "^4.0.2", + "which": "^4.0.0" + }, + "bin": { + "dotenvx": "src/cli/dotenvx.js" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/@dotenvx/dotenvx/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@ecies/ciphers": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.4.tgz", + "integrity": "sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==", + "license": "MIT", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" + } + }, "node_modules/@emnapi/core": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", @@ -935,6 +1519,165 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@inquirer/confirm": { + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.16.tgz", + "integrity": "sha512-j1a5VstaK5KQy8Mu8cHmuQvN1Zc62TbLhjJxwHvKPPKEoowSF6h/0UdOpA9DNdWZ+9Inq73+puRq1df6OJ8Sag==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.2.0", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.2.0.tgz", + "integrity": "sha512-NyDSjPqhSvpZEMZrLCYUquWNl+XC/moEcVFqS55IEYIYsY0a1cUCevSqk7ctOlnm/RaSBU5psFryNlxcmGrjaA==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", + "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", + "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/@internationalized/date": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", @@ -972,6 +1715,27 @@ "@swc/helpers": "^0.5.0" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1026,6 +1790,16 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1244,6 +2018,46 @@ "@langchain/core": ">=0.3.68 <0.4.0" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.5.tgz", + "integrity": "sha512-QakrKIGniGuRVfWBdMsDea/dx1PNE739QJ7gCM41s9q+qaCYTHCdsIBXQVVXry3mfWAiaM9kT22Hyz53Uw8mfg==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.39.6", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.6.tgz", + "integrity": "sha512-bndDP83naYYkfayr/qhBHMhk0YGwS1iv6vaEGcr0SQbO0IZtbOPqjKjds/WcG+bJA+1T5vCx6kprKOzn5Bg+Vw==", + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", @@ -3094,6 +3908,45 @@ "react-dom": ">=18" } }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3139,6 +3992,28 @@ "node": ">=12.4.0" } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "license": "MIT" + }, "node_modules/@opentelemetry/api": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", @@ -6423,6 +7298,24 @@ "dev": true, "license": "MIT" }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -6486,33 +7379,6 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@ts-morph/common": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.19.0.tgz", - "integrity": "sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==", - "license": "MIT", - "dependencies": { - "fast-glob": "^3.2.12", - "minimatch": "^7.4.3", - "mkdirp": "^2.1.6", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@ts-morph/common/node_modules/minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -6524,11 +7390,10 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/bcryptjs": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", - "dev": true, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "license": "MIT" }, "node_modules/@types/d3-array": { @@ -6687,7 +7552,7 @@ "version": "20.5.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/prop-types": { @@ -6723,6 +7588,12 @@ "license": "MIT", "peer": true }, + "node_modules/@types/statuses": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -7203,6 +8074,19 @@ "win32" ] }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -7226,12 +8110,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/add": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz", - "integrity": "sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q==", - "license": "MIT" - }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -7271,7 +8149,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -7332,6 +8209,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz", + "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -7555,6 +8441,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -7682,12 +8580,6 @@ ], "license": "MIT" }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", - "license": "MIT" - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -7700,15 +8592,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/brace-expansion": { @@ -7736,7 +8637,6 @@ "version": "4.25.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7765,30 +8665,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -7800,6 +8676,15 @@ "node": ">=10.16.0" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -7823,7 +8708,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -7837,7 +8721,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -8034,7 +8917,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" @@ -8129,19 +9011,94 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/clsx": { @@ -8153,28 +9110,6 @@ "node": ">=6" } }, - "node_modules/cmdk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", - "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-id": "^1.1.0", - "@radix-ui/react-primitive": "^2.0.2" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/code-block-writer": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz", - "integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==", - "license": "MIT" - }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -8272,30 +9207,62 @@ "simple-wcswidth": "^1.0.1" } }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">=14" + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">= 0.10" } }, "node_modules/cross-spawn": { @@ -8583,6 +9550,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8599,18 +9580,6 @@ "node": ">=0.10.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -8647,6 +9616,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -8690,15 +9668,6 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "license": "Apache-2.0" }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/diff-match-patch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", @@ -8747,11 +9716,22 @@ "csstype": "^3.0.2" } }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -8768,11 +9748,33 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "license": "MIT" }, + "node_modules/eciesjs": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.15.tgz", + "integrity": "sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==", + "license": "MIT", + "dependencies": { + "@ecies/ciphers": "^0.2.3", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.1", + "@noble/hashes": "^1.8.0" + }, + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.179", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", - "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { @@ -8781,6 +9783,15 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -8790,6 +9801,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/environment": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", @@ -8885,7 +9905,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8895,7 +9914,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8933,7 +9951,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -8993,12 +10010,17 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -9716,6 +10738,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -9772,6 +10807,15 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -9779,6 +10823,27 @@ "dev": true, "license": "MIT" }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -9803,6 +10868,63 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -9813,7 +10935,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -9864,7 +10985,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -9915,6 +11035,33 @@ "node": ">= 8" } }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -9940,6 +11087,23 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -10032,6 +11196,15 @@ "node": ">=12.20.0" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -10073,10 +11246,19 @@ } } }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -10148,11 +11330,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fuzzysort": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz", + "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==", + "license": "MIT" + }, + "node_modules/fzf": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.5.2.tgz", + "integrity": "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==", + "license": "BSD-3-Clause" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-east-asian-width": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -10165,7 +11376,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -10195,11 +11405,22 @@ "node": ">=6" } }, + "node_modules/get-own-enumerable-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-own-enumerable-keys/-/get-own-enumerable-keys-1.0.0.tgz", + "integrity": "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -10345,7 +11566,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10367,6 +11587,15 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -10422,7 +11651,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10499,6 +11727,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "license": "MIT" + }, "node_modules/html-url-attributes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", @@ -10509,17 +11743,29 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/https-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.2.1.tgz", - "integrity": "sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 14" + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" } }, "node_modules/human-signals": { @@ -10548,31 +11794,22 @@ "url": "https://github.com/sponsors/typicode" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -10583,6 +11820,8 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "license": "MIT", + "optional": true, + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -10674,6 +11913,15 @@ "tslib": "^2.8.0" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -10987,6 +12235,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -11013,6 +12267,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz", + "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -11035,6 +12301,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -11054,6 +12326,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-regexp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz", + "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", @@ -11087,6 +12371,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -11146,18 +12431,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -11298,6 +12571,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -11321,7 +12606,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -11753,34 +13037,6 @@ "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", "license": "MIT" }, - "node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", - "license": "MIT", - "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -11948,9 +13204,9 @@ "license": "ISC" }, "node_modules/lucide-react": { - "version": "0.471.2", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.471.2.tgz", - "integrity": "sha512-A8fDycQxGeaSOTaI7Bm4fg8LBXO7Qr9ORAX47bDRvugCsjLIliugQO0PkKFoeAD57LIQwlWKd3NIQ3J7hYp84g==", + "version": "0.543.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.543.0.tgz", + "integrity": "sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -11972,7 +13228,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -12131,6 +13386,27 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12601,10 +13877,32 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -12617,7 +13915,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12659,21 +13956,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/motion-dom": { "version": "11.18.1", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", @@ -12695,6 +13977,62 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/msw": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.11.1.tgz", + "integrity": "sha512-dGSRx0AJmQVQfpGXTsAAq4JFdwdhOBdJ6sJS/jnN0ac3s0NZB6daacHF1z5Pefx+IejmvuiLWw260RlyQOf3sQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.1", + "@bundled-es-modules/statuses": "^1.0.1", + "@inquirer/confirm": "^5.0.0", + "@mswjs/interceptors": "^0.39.1", + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "path-to-regexp": "^6.3.0", + "picocolors": "^1.1.1", + "strict-event-emitter": "^0.5.1", + "tough-cookie": "^6.0.0", + "type-fest": "^4.26.1", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mustache": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", @@ -12705,6 +14043,15 @@ "mustache": "bin/mustache" } }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -12757,6 +14104,15 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next": { "version": "14.2.32", "resolved": "https://registry.npmjs.org/next/-/next-14.2.32.tgz", @@ -12903,11 +14259,28 @@ "node": ">=10.5.0" } }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, "license": "MIT" }, "node_modules/normalize-path": { @@ -12933,6 +14306,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^4.0.0" @@ -12948,6 +14322,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -12987,7 +14362,6 @@ "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -13006,6 +14380,15 @@ "node": ">= 0.4" } }, + "node_modules/object-treeify": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/object.assign": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", @@ -13096,11 +14479,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -13110,6 +14504,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" @@ -13160,128 +14555,11 @@ "node": ">= 0.8.0" } }, - "node_modules/ora": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz", - "integrity": "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==", - "license": "MIT", - "dependencies": { - "chalk": "^5.0.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.6.1", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.1.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "strip-ansi": "^7.0.1", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "license": "MIT", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ora/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "license": "MIT" }, "node_modules/own-keys": { "version": "1.0.1", @@ -13394,6 +14672,12 @@ "node": ">=8" } }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13449,6 +14733,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -13506,10 +14811,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13564,6 +14876,15 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/playwright": { "version": "1.53.2", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.2.tgz", @@ -13899,6 +15220,21 @@ } } }, + "node_modules/pretty-ms": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", + "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -13933,16 +15269,43 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -14040,6 +15403,46 @@ } } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -14066,9 +15469,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.59.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.59.0.tgz", - "integrity": "sha512-kmkek2/8grqarTJExFNjy+RXDIP8yM+QTl3QL6m6Q8b2bih4ltmiXxH7T9n+yXNK477xPh5yZT/6vD8sYGzJTA==", + "version": "7.62.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz", + "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -14240,20 +15643,6 @@ "pify": "^2.3.0" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -14266,6 +15655,22 @@ "node": ">=8.10.0" } }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, "node_modules/recharts": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", @@ -14410,6 +15815,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -14453,7 +15867,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, "license": "MIT", "dependencies": { "onetime": "^7.0.0", @@ -14470,7 +15883,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, "license": "MIT", "dependencies": { "mimic-function": "^5.0.0" @@ -14572,6 +15984,32 @@ "node": "*" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/rss-parser": { "version": "3.13.0", "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.13.0.tgz", @@ -14690,6 +16128,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", @@ -14732,6 +16176,43 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/server-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", @@ -14787,35 +16268,99 @@ "node": ">= 0.4" } }, - "node_modules/shadcn-ui": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.2.3.tgz", - "integrity": "sha512-Bf2y8d5VusDbCs5l/SRmFTJ2tW9oBvIDWL1xmmURKuxn8rznXApoTdflPJ+Q68zKFXmIh6cYd4cJ8I8nzOkoAQ==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shadcn": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-3.2.1.tgz", + "integrity": "sha512-j+yLAXa6CFBz96+O6dtiA+BllDOokYH65eofCYbPY2+NBsFYiSKbyfj6psbujNfng9HP7N9/+j6Uzo2iYxRqtw==", "license": "MIT", "dependencies": { - "@antfu/ni": "^0.21.4", - "chalk": "5.2.0", - "commander": "^10.0.0", - "cosmiconfig": "^8.1.3", - "diff": "^5.1.0", - "execa": "^7.0.0", - "fs-extra": "^11.1.0", - "https-proxy-agent": "^6.2.0", - "node-fetch": "^3.3.0", - "ora": "^6.1.2", + "@antfu/ni": "^25.0.0", + "@babel/core": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/plugin-transform-typescript": "^7.28.0", + "@dotenvx/dotenvx": "^1.48.4", + "@modelcontextprotocol/sdk": "^1.17.2", + "commander": "^14.0.0", + "cosmiconfig": "^9.0.0", + "dedent": "^1.6.0", + "deepmerge": "^4.3.1", + "diff": "^8.0.2", + "execa": "^9.6.0", + "fast-glob": "^3.3.3", + "fs-extra": "^11.3.1", + "fuzzysort": "^3.1.0", + "https-proxy-agent": "^7.0.6", + "kleur": "^4.1.5", + "msw": "^2.10.4", + "node-fetch": "^3.3.2", + "ora": "^8.2.0", + "postcss": "^8.5.6", "prompts": "^2.4.2", - "ts-morph": "^18.0.0", + "recast": "^0.23.11", + "stringify-object": "^5.0.0", + "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", - "zod": "^3.20.2" + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.6" }, "bin": { - "shadcn-ui": "dist/index.js" + "shadcn": "dist/index.js" } }, - "node_modules/shadcn-ui/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "node_modules/shadcn/node_modules/@antfu/ni": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-25.0.0.tgz", + "integrity": "sha512-9q/yCljni37pkMr4sPrI3G4jqdIk074+iukc5aFJl7kmDCCsiJrbZ6zKxnES1Gwg+i9RcDZwvktl23puGslmvA==", + "license": "MIT", + "dependencies": { + "ansis": "^4.0.0", + "fzf": "^0.5.2", + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "na": "bin/na.mjs", + "nci": "bin/nci.mjs", + "ni": "bin/ni.mjs", + "nlx": "bin/nlx.mjs", + "nr": "bin/nr.mjs", + "nun": "bin/nun.mjs", + "nup": "bin/nup.mjs" + } + }, + "node_modules/shadcn/node_modules/@ts-morph/common": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz", + "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.3.3", + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/shadcn/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/shadcn/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -14824,60 +16369,151 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/shadcn-ui/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "node_modules/shadcn/node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", + "license": "MIT" + }, + "node_modules/shadcn/node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=20" } }, - "node_modules/shadcn-ui/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "node_modules/shadcn/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/shadcn/node_modules/diff": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/shadcn/node_modules/emoji-regex": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "license": "MIT" + }, + "node_modules/shadcn/node_modules/execa": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", + "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/shadcn-ui/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/shadcn/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shadcn-ui/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "license": "Apache-2.0", + "node_modules/shadcn/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, "engines": { - "node": ">=14.18.0" + "node": ">= 14" } }, - "node_modules/shadcn-ui/node_modules/json5": { + "node_modules/shadcn/node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/shadcn/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", @@ -14889,31 +16525,204 @@ "node": ">=6" } }, - "node_modules/shadcn-ui/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/shadcn/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "node": ">=6" } }, - "node_modules/shadcn-ui/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" + "node_modules/shadcn/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/shadcn-ui/node_modules/tsconfig-paths": { + "node_modules/shadcn/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/shadcn/node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/shadcn/node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/shadcn/node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shadcn/node_modules/ts-morph": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz", + "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==", + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.27.0", + "code-block-writer": "^13.0.3" + } + }, + "node_modules/shadcn/node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", @@ -14991,7 +16800,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -15011,7 +16819,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -15028,7 +16835,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -15047,7 +16853,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -15143,6 +16948,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -15169,19 +16983,13 @@ "dev": true, "license": "MIT" }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", - "dependencies": { - "bl": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, "node_modules/stop-iteration-iterator": { @@ -15206,14 +17014,11 @@ "node": ">=10.0.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "license": "MIT" }, "node_modules/string-argv": { "version": "0.3.2", @@ -15426,6 +17231,23 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/stringify-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-5.0.0.tgz", + "integrity": "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-keys": "^1.0.0", + "is-obj": "^3.0.0", + "is-regexp": "^3.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/stringify-object?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15464,6 +17286,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -15766,6 +17589,12 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", @@ -15811,6 +17640,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tldts": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.13.tgz", + "integrity": "sha512-z/SgnxiICGb7Gli0z7ci9BZdjy1tQORUbdmzEUA7NbIJKWhdONn78Ji8gV0PAGfHPyEd+I+W2rMzhLjWkv2Olg==", + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.13" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.13.tgz", + "integrity": "sha512-Td0LeWLgXJGsikI4mO82fRexgPCEyTcwWiXJERF/GBHX3Dm+HQq/wx4HnYowCbiwQ8d+ENLZc+ktbZw8H+0oEA==", + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15823,6 +17670,27 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -15862,16 +17730,6 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, - "node_modules/ts-morph": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-18.0.0.tgz", - "integrity": "sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==", - "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.19.0", - "code-block-writer": "^12.0.0" - } - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -15917,6 +17775,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -16028,6 +17900,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -16124,6 +18008,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unrs-resolver": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.10.1.tgz", @@ -16163,7 +18056,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -16194,7 +18086,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -16297,22 +18188,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/usehooks-ts": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.1.tgz", - "integrity": "sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.debounce": "^4.0.8" - }, - "engines": { - "node": ">=16.15.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16332,6 +18207,15 @@ "uuid": "dist/esm/bin/uuid" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -16382,15 +18266,6 @@ "d3-timer": "^3.0.1" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -16627,7 +18502,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/xml2js": { @@ -16652,6 +18526,21 @@ "node": ">=4.0" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, "node_modules/yaml": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", @@ -16664,6 +18553,62 @@ "node": ">= 14.6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -16677,6 +18622,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.25.73", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.73.tgz", diff --git a/ui/package.json b/ui/package.json index ebd9e3279c..e5c6c31cd3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,93 +1,4 @@ { - "dependencies": { - "@hookform/resolvers": "^3.9.0", - "@langchain/langgraph-supervisor": "^0.0.12", - "@langchain/openai": "^0.6.9", - "@next/third-parties": "^15.3.3", - "@nextui-org/react": "2.4.8", - "@nextui-org/system": "2.2.1", - "@nextui-org/theme": "2.2.5", - "@radix-ui/react-alert-dialog": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-slot": "^1.1.1", - "@radix-ui/react-toast": "^1.2.4", - "@react-aria/ssr": "3.9.4", - "@react-aria/visually-hidden": "3.8.12", - "@tailwindcss/typography": "^0.5.16", - "@tanstack/react-table": "^8.19.3", - "@types/js-yaml": "^4.0.9", - "add": "^2.0.6", - "ai": "^4.3.16", - "alert": "^6.0.2", - "bcryptjs": "^2.4.3", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "cmdk": "^1.0.0", - "date-fns": "^4.1.0", - "framer-motion": "^11.16.0", - "immer": "^10.1.1", - "intl-messageformat": "^10.5.0", - "jose": "^5.9.3", - "js-yaml": "^4.1.0", - "jwt-decode": "^4.0.0", - "lucide-react": "^0.471.0", - "marked": "^15.0.12", - "next": "^14.2.32", - "next-auth": "^5.0.0-beta.25", - "next-themes": "^0.2.1", - "radix-ui": "^1.1.3", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-hook-form": "^7.52.2", - "react-markdown": "^10.1.0", - "recharts": "^2.15.2", - "rss-parser": "^3.13.0", - "server-only": "^0.0.1", - "shadcn-ui": "^0.2.3", - "sharp": "^0.33.5", - "tailwind-merge": "^3.2.0", - "tailwindcss-animate": "^1.0.7", - "uuid": "^11.0.5", - "zod": "^3.23.8", - "zustand": "^4.5.5" - }, - "devDependencies": { - "@iconify/react": "^5.2.0", - "@playwright/test": "^1.53.1", - "@types/bcryptjs": "^2.4.6", - "@types/node": "20.5.7", - "@types/react": "18.3.3", - "@types/react-dom": "18.3.0", - "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", - "autoprefixer": "10.4.19", - "eslint": "^8.56.0", - "eslint-config-next": "^14.2.32", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.23.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-security": "^3.0.1", - "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^3.2.0", - "husky": "^9.0.11", - "lint-staged": "^15.2.7", - "postcss": "8.4.38", - "prettier": "^3.3.3", - "prettier-plugin-tailwindcss": "^0.6.8", - "tailwind-variants": "0.1.20", - "tailwindcss": "3.4.3", - "typescript": "5.5.4", - "usehooks-ts": "^3.1.0" - }, "name": "prowler-next-app", "private": true, "scripts": { @@ -95,6 +6,8 @@ "build": "next build", "start": "next start", "start:standalone": "node .next/standalone/server.js", + "deps:log": "node scripts/update-dependency-log.js", + "postinstall": "node -e \"const fs=require('fs'); if(fs.existsSync('scripts/update-dependency-log.js')) require('./scripts/update-dependency-log.js'); else console.log('skip deps:log (script missing)');\"", "typecheck": "tsc", "healthcheck": "npm run typecheck && npm run lint:check", "lint:check": "eslint . --ext .ts,.tsx -c .eslintrc.cjs", @@ -109,6 +22,89 @@ "test:e2e:report": "playwright show-report", "test:e2e:install": "playwright install" }, + "dependencies": { + "@hookform/resolvers": "3.10.0", + "@langchain/langgraph-supervisor": "0.0.12", + "@langchain/openai": "0.6.9", + "@next/third-parties": "15.3.5", + "@nextui-org/react": "2.4.8", + "@nextui-org/system": "2.2.1", + "@nextui-org/theme": "2.2.5", + "@radix-ui/react-alert-dialog": "1.1.14", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-dropdown-menu": "2.1.15", + "@radix-ui/react-icons": "1.3.2", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-toast": "1.2.14", + "@react-aria/ssr": "3.9.4", + "@react-aria/visually-hidden": "3.8.12", + "@tailwindcss/typography": "0.5.16", + "@tanstack/react-table": "8.21.3", + "@types/js-yaml": "4.0.9", + "ai": "4.3.16", + "alert": "6.0.2", + "class-variance-authority": "0.7.1", + "clsx": "2.1.1", + "date-fns": "4.1.0", + "framer-motion": "11.18.2", + "intl-messageformat": "10.7.16", + "jose": "5.10.0", + "js-yaml": "4.1.0", + "jwt-decode": "4.0.0", + "lucide-react": "0.543.0", + "marked": "15.0.12", + "next": "14.2.32", + "next-auth": "5.0.0-beta.29", + "next-themes": "0.2.1", + "radix-ui": "1.4.2", + "react": "18.3.1", + "react-dom": "18.3.1", + "react-hook-form": "7.62.0", + "react-markdown": "10.1.0", + "recharts": "2.15.4", + "rss-parser": "3.13.0", + "server-only": "0.0.1", + "shadcn": "3.2.1", + "sharp": "0.33.5", + "tailwind-merge": "3.3.1", + "tailwindcss-animate": "1.0.7", + "uuid": "11.1.0", + "zod": "3.25.73", + "zustand": "4.5.7" + }, + "devDependencies": { + "@iconify/react": "5.2.1", + "@playwright/test": "1.53.2", + "@types/node": "20.5.7", + "@types/react": "18.3.3", + "@types/react-dom": "18.3.0", + "@types/uuid": "10.0.0", + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.18.0", + "autoprefixer": "10.4.19", + "eslint": "8.57.1", + "eslint-config-next": "14.2.32", + "eslint-config-prettier": "10.1.5", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-jsx-a11y": "6.10.2", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-prettier": "5.5.1", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-security": "3.0.1", + "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-unused-imports": "3.2.0", + "husky": "9.1.7", + "lint-staged": "15.5.2", + "postcss": "8.4.38", + "prettier": "3.6.2", + "prettier-plugin-tailwindcss": "0.6.13", + "tailwind-variants": "0.1.20", + "tailwindcss": "3.4.3", + "typescript": "5.5.4" + }, "overrides": { "@react-types/shared": "3.26.0" }, diff --git a/ui/scripts/update-dependency-log.js b/ui/scripts/update-dependency-log.js new file mode 100644 index 0000000000..ac6449e6f7 --- /dev/null +++ b/ui/scripts/update-dependency-log.js @@ -0,0 +1,95 @@ +const fs = require('fs'); +const path = require('path'); + +function readJSON(p) { + return JSON.parse(fs.readFileSync(p, 'utf8')); +} + +function getInstalledVersion(pkgName) { + try { + const parts = pkgName.split('/'); + const pkgPath = path.join('node_modules', ...parts, 'package.json'); + const meta = readJSON(pkgPath); + return meta.version; + } catch (e) { + return null; + } +} + +function collect(sectionName, obj) { + if (!obj) return []; + return Object.entries(obj).map(([name, declared]) => { + const installed = getInstalledVersion(name); + return { + section: sectionName, + name, + from: declared, + to: installed || null, + strategy: 'installed', + }; + }); +} + +function main() { + // If node_modules is missing, skip to avoid generating noisy diffs + if (!fs.existsSync('node_modules')) { + console.log('Skip: node_modules not found. Run npm install first.'); + return; + } + + const pkg = readJSON('package.json'); + const entries = [ + ...collect('dependencies', pkg.dependencies), + ...collect('devDependencies', pkg.devDependencies), + ]; + + // Stable sort by section then name + entries.sort((a, b) => + a.section === b.section ? a.name.localeCompare(b.name) : a.section.localeCompare(b.section) + ); + + const outPath = path.join(process.cwd(), 'dependency-log.json'); + // Merge with previous to preserve generatedAt when unchanged + let prevMap = new Map(); + if (fs.existsSync(outPath)) { + try { + const prev = JSON.parse(fs.readFileSync(outPath, 'utf8')); + for (const e of prev) { + prevMap.set(`${e.section}::${e.name}`, e); + } + } catch {} + } + + const now = new Date().toISOString(); + const merged = entries.map((e) => { + const key = `${e.section}::${e.name}`; + const prev = prevMap.get(key); + if (!prev) { + // New entry: keep declared as from + return { ...e, generatedAt: now }; + } + + // If installed version changed, set from to previous installed version + if (prev.to !== e.to) { + return { ...e, from: prev.to, generatedAt: now }; + } + + // Otherwise preserve previous 'from' and timestamp + return { ...e, from: prev.from, generatedAt: prev.generatedAt || now }; + }); + + const nextContent = JSON.stringify(merged, null, 2) + '\n'; + if (fs.existsSync(outPath)) { + try { + const prevContent = fs.readFileSync(outPath, 'utf8'); + if (prevContent === nextContent) { + console.log(`No changes for ${outPath} (entries: ${entries.length}).`); + return; + } + } catch {} + } + fs.writeFileSync(outPath, nextContent); + console.log(`Updated ${outPath} with ${entries.length} entries.`); +} + +main(); From b512f6c421ad178c0a326e233e04285278c48720 Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:55:16 +0200 Subject: [PATCH 5/6] fix(firehose): false positive in `firehose_stream_encrypted_at_rest` (#8599) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + .../firehose_stream_encrypted_at_rest.py | 24 ++- ...fka_cluster_encryption_at_rest_uses_cmk.py | 7 +- ...fka_cluster_enhanced_monitoring_enabled.py | 7 +- ...a_cluster_in_transit_encryption_enabled.py | 7 +- .../kafka_cluster_is_public.py | 7 +- ...uster_mutual_tls_authentication_enabled.py | 7 +- ...ka_cluster_unrestricted_access_disabled.py | 7 +- .../kafka_cluster_uses_latest_version.py | 7 +- .../aws/services/kafka/kafka_service.py | 146 ++++++++++++----- ...luster_encryption_at_rest_uses_cmk_test.py | 61 +++++++ ...luster_enhanced_monitoring_enabled_test.py | 74 +++++++-- ...ster_in_transit_encryption_enabled_test.py | 80 ++++++++-- .../kafka_cluster_is_public_test.py | 74 +++++++-- ..._mutual_tls_authentication_enabled_test.py | 74 +++++++-- ...uster_unrestricted_access_disabled_test.py | 74 +++++++-- .../kafka_cluster_uses_latest_version_test.py | 79 +++++++-- .../aws/services/kafka/kafka_service_test.py | 151 +++++++++++------- 18 files changed, 724 insertions(+), 163 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 9df610cdd9..5d873f663b 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Fixed - Replaced old check id with new ones for compliance files [(#8682)](https://github.com/prowler-cloud/prowler/pull/8682) +- `firehose_stream_encrypted_at_rest` check false positives and new api call in kafka service [(#8599)](https://github.com/prowler-cloud/prowler/pull/8599) - Replace defender rules policies key to use old name [(#8702)](https://github.com/prowler-cloud/prowler/pull/8702) ## [v5.12.0] (Prowler v5.12.0) diff --git a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py index 69d1711f73..21ca07a920 100644 --- a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py +++ b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py @@ -3,6 +3,7 @@ from typing import List from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.services.firehose.firehose_client import firehose_client from prowler.providers.aws.services.firehose.firehose_service import EncryptionStatus +from prowler.providers.aws.services.kafka.kafka_client import kafka_client from prowler.providers.aws.services.kinesis.kinesis_client import kinesis_client from prowler.providers.aws.services.kinesis.kinesis_service import EncryptionType @@ -37,7 +38,28 @@ class firehose_stream_encrypted_at_rest(Check): report.status = "PASS" report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled but the source stream {source_stream.name} has at rest encryption enabled." - # Check if the stream has encryption enabled directly + # MSK source - check if the MSK cluster has encryption at rest with CMK + elif stream.delivery_stream_type == "MSKAsSource": + msk_cluster_arn = stream.source.msk.msk_cluster_arn + if msk_cluster_arn: + msk_cluster = None + for cluster in kafka_client.clusters.values(): + if cluster.arn == msk_cluster_arn: + msk_cluster = cluster + break + + if msk_cluster: + # All MSK clusters (both provisioned and serverless) always have encryption at rest enabled by AWS + # AWS MSK always encrypts data at rest - either with AWS managed keys or CMK + report.status = "PASS" + if msk_cluster.kafka_version == "SERVERLESS": + report.status_extended = f"Firehose Stream {stream.name} uses MSK serverless source which always has encryption at rest enabled by default." + else: + report.status_extended = f"Firehose Stream {stream.name} uses MSK provisioned source which always has encryption at rest enabled by AWS (either with AWS managed keys or CMK)." + else: + report.status_extended = f"Firehose Stream {stream.name} uses MSK source which always has encryption at rest enabled by AWS." + + # Check if the stream has encryption enabled directly (DirectPut or DatabaseAsSource cases) elif stream.kms_encryption == EncryptionStatus.ENABLED: report.status = "PASS" report.status_extended = f"Firehose Stream {stream.name} does have at rest encryption enabled." diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk.py b/prowler/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk.py index 2dce9437ad..b110804028 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk.py @@ -12,7 +12,12 @@ class kafka_cluster_encryption_at_rest_uses_cmk(Check): report.status = "FAIL" report.status_extended = f"Kafka cluster '{cluster.name}' does not have encryption at rest enabled with a CMK." - if any( + # Serverless clusters always have encryption at rest enabled by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and always has encryption at rest enabled by default." + # For provisioned clusters, check if they use a customer managed KMS key + elif any( ( cluster.data_volume_kms_key_id == key.arn and getattr(key, "manager", "") == "CUSTOMER" diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled.py b/prowler/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled.py index 2bf0d38391..03fb098eef 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled.py @@ -13,7 +13,12 @@ class kafka_cluster_enhanced_monitoring_enabled(Check): f"Kafka cluster '{cluster.name}' has enhanced monitoring enabled." ) - if cluster.enhanced_monitoring == "DEFAULT": + # Serverless clusters always have enhanced monitoring enabled by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and always has enhanced monitoring enabled by default." + # For provisioned clusters, check the enhanced monitoring configuration + elif cluster.enhanced_monitoring == "DEFAULT": report.status = "FAIL" report.status_extended = f"Kafka cluster '{cluster.name}' does not have enhanced monitoring enabled." diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled.py b/prowler/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled.py index 7b37fe5a17..5e9bd77af0 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled.py @@ -11,7 +11,12 @@ class kafka_cluster_in_transit_encryption_enabled(Check): report.status = "FAIL" report.status_extended = f"Kafka cluster '{cluster.name}' does not have encryption in transit enabled." - if ( + # Serverless clusters always have encryption in transit enabled by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and always has encryption in transit enabled by default." + # For provisioned clusters, check the encryption configuration + elif ( cluster.encryption_in_transit.client_broker == "TLS" and cluster.encryption_in_transit.in_cluster ): diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py b/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py index 426ff04490..4dabf61fce 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py @@ -13,7 +13,12 @@ class kafka_cluster_is_public(Check): f"Kafka cluster {cluster.name} is publicly accessible." ) - if not cluster.public_access: + # Serverless clusters are always private by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster {cluster.name} is serverless and always private by default." + # For provisioned clusters, check the public access configuration + elif not cluster.public_access: report.status = "PASS" report.status_extended = ( f"Kafka cluster {cluster.name} is not publicly accessible." diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled.py b/prowler/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled.py index 0e07e34107..98dcf15b44 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled.py @@ -11,7 +11,12 @@ class kafka_cluster_mutual_tls_authentication_enabled(Check): report.status = "FAIL" report.status_extended = f"Kafka cluster '{cluster.name}' does not have mutual TLS authentication enabled." - if cluster.tls_authentication: + # Serverless clusters always have TLS authentication enabled by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and always has TLS authentication enabled by default." + # For provisioned clusters, check the TLS configuration + elif cluster.tls_authentication: report.status = "PASS" report.status_extended = f"Kafka cluster '{cluster.name}' has mutual TLS authentication enabled." diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled.py b/prowler/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled.py index f96abbdb06..219affd8a5 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled.py @@ -13,7 +13,12 @@ class kafka_cluster_unrestricted_access_disabled(Check): f"Kafka cluster '{cluster.name}' has unrestricted access enabled." ) - if not cluster.unauthentication_access: + # Serverless clusters always require authentication by default + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and always requires authentication by default." + # For provisioned clusters, check the unauthenticated access configuration + elif not cluster.unauthentication_access: report.status = "PASS" report.status_extended = f"Kafka cluster '{cluster.name}' does not have unrestricted access enabled." diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version.py b/prowler/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version.py index 32c1793384..e19686c9a6 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version.py @@ -13,7 +13,12 @@ class kafka_cluster_uses_latest_version(Check): f"Kafka cluster '{cluster.name}' is using the latest version." ) - if cluster.kafka_version != kafka_client.kafka_versions[-1].version: + # Serverless clusters don't have specific Kafka versions - AWS manages them automatically + if cluster.kafka_version == "SERVERLESS": + report.status = "PASS" + report.status_extended = f"Kafka cluster '{cluster.name}' is serverless and AWS automatically manages the Kafka version." + # For provisioned clusters, check if they're using the latest version + elif cluster.kafka_version != kafka_client.kafka_versions[-1].version: report.status = "FAIL" report.status_extended = ( f"Kafka cluster '{cluster.name}' is not using the latest version." diff --git a/prowler/providers/aws/services/kafka/kafka_service.py b/prowler/providers/aws/services/kafka/kafka_service.py index 4197e543c4..3b52063206 100644 --- a/prowler/providers/aws/services/kafka/kafka_service.py +++ b/prowler/providers/aws/services/kafka/kafka_service.py @@ -15,61 +15,133 @@ class Kafka(AWSService): self.__threading_call__(self._list_kafka_versions) def _list_clusters(self, regional_client): + logger.info(f"Kafka - Listing clusters in region {regional_client.region}...") try: - cluster_paginator = regional_client.get_paginator("list_clusters") + # Use list_clusters_v2 to support both provisioned and serverless clusters + cluster_paginator = regional_client.get_paginator("list_clusters_v2") + logger.info( + f"Kafka - Paginator created for region {regional_client.region}" + ) for page in cluster_paginator.paginate(): + logger.info( + f"Kafka - Processing page with {len(page.get('ClusterInfoList', []))} clusters in region {regional_client.region}" + ) for cluster in page["ClusterInfoList"]: + logger.info( + f"Kafka - Found cluster: {cluster.get('ClusterName', 'Unknown')} in region {regional_client.region}" + ) arn = cluster.get( "ClusterArn", f"{self.account_arn_template}/{cluster.get('ClusterName', '')}", ) + cluster_type = cluster.get("ClusterType", "UNKNOWN") if not self.audit_resources or is_resource_filtered( arn, self.audit_resources ): - self.clusters[cluster.get("ClusterArn", "")] = Cluster( - id=arn.split(":")[-1].split("/")[-1], - name=cluster.get("ClusterName", ""), - arn=arn, - region=regional_client.region, - tags=list(cluster.get("Tags", {})), - state=cluster.get("State", ""), - kafka_version=cluster.get( - "CurrentBrokerSoftwareInfo", {} - ).get("KafkaVersion", ""), - data_volume_kms_key_id=cluster.get("EncryptionInfo", {}) - .get("EncryptionAtRest", {}) - .get("DataVolumeKMSKeyId", ""), - encryption_in_transit=EncryptionInTransit( - client_broker=cluster.get("EncryptionInfo", {}) - .get("EncryptionInTransit", {}) - .get("ClientBroker", "PLAINTEXT"), - in_cluster=cluster.get("EncryptionInfo", {}) - .get("EncryptionInTransit", {}) - .get("InCluster", False), - ), - tls_authentication=cluster.get("ClientAuthentication", {}) - .get("Tls", {}) - .get("Enabled", False), - public_access=cluster.get("BrokerNodeGroupInfo", {}) - .get("ConnectivityInfo", {}) - .get("PublicAccess", {}) - .get("Type", "SERVICE_PROVIDED_EIPS") - != "DISABLED", - unauthentication_access=cluster.get( - "ClientAuthentication", {} + # Handle provisioned clusters + if cluster_type == "PROVISIONED" and "Provisioned" in cluster: + provisioned = cluster["Provisioned"] + self.clusters[cluster.get("ClusterArn", "")] = Cluster( + id=arn.split(":")[-1].split("/")[-1], + name=cluster.get("ClusterName", ""), + arn=arn, + region=regional_client.region, + tags=( + list(cluster.get("Tags", {}).values()) + if cluster.get("Tags") + else [] + ), + state=cluster.get("State", ""), + kafka_version=provisioned.get( + "CurrentBrokerSoftwareInfo", {} + ).get("KafkaVersion", ""), + data_volume_kms_key_id=provisioned.get( + "EncryptionInfo", {} + ) + .get("EncryptionAtRest", {}) + .get("DataVolumeKMSKeyId", ""), + encryption_in_transit=EncryptionInTransit( + client_broker=provisioned.get("EncryptionInfo", {}) + .get("EncryptionInTransit", {}) + .get("ClientBroker", "PLAINTEXT"), + in_cluster=provisioned.get("EncryptionInfo", {}) + .get("EncryptionInTransit", {}) + .get("InCluster", False), + ), + tls_authentication=provisioned.get( + "ClientAuthentication", {} + ) + .get("Tls", {}) + .get("Enabled", False), + public_access=provisioned.get("BrokerNodeGroupInfo", {}) + .get("ConnectivityInfo", {}) + .get("PublicAccess", {}) + .get("Type", "SERVICE_PROVIDED_EIPS") + != "DISABLED", + unauthentication_access=provisioned.get( + "ClientAuthentication", {} + ) + .get("Unauthenticated", {}) + .get("Enabled", False), + enhanced_monitoring=provisioned.get( + "EnhancedMonitoring", "DEFAULT" + ), ) - .get("Unauthenticated", {}) - .get("Enabled", False), - enhanced_monitoring=cluster.get( - "EnhancedMonitoring", "DEFAULT" - ), + logger.info( + f"Kafka - Added provisioned cluster {cluster.get('ClusterName', 'Unknown')} to clusters dict" + ) + + # Handle serverless clusters + elif cluster_type == "SERVERLESS" and "Serverless" in cluster: + # For serverless clusters, encryption is always enabled by default + # We'll create a Cluster object with default encryption values + self.clusters[cluster.get("ClusterArn", "")] = Cluster( + id=arn.split(":")[-1].split("/")[-1], + name=cluster.get("ClusterName", ""), + arn=arn, + region=regional_client.region, + tags=( + list(cluster.get("Tags", {}).values()) + if cluster.get("Tags") + else [] + ), + state=cluster.get("State", ""), + kafka_version="SERVERLESS", # Serverless doesn't have specific Kafka version + data_volume_kms_key_id="AWS_MANAGED", # Serverless uses AWS managed keys + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", # Serverless always has TLS enabled + in_cluster=True, # Serverless always has in-cluster encryption + ), + tls_authentication=True, # Serverless always has TLS authentication + public_access=False, # Serverless clusters are always private + unauthentication_access=False, # Serverless requires authentication + enhanced_monitoring="DEFAULT", + ) + logger.info( + f"Kafka - Added serverless cluster {cluster.get('ClusterName', 'Unknown')} to clusters dict" + ) + + else: + logger.warning( + f"Kafka - Unknown cluster type {cluster_type} for cluster {cluster.get('ClusterName', 'Unknown')}" + ) + else: + logger.info( + f"Kafka - Cluster {cluster.get('ClusterName', 'Unknown')} filtered out by audit_resources" ) + + logger.info( + f"Kafka - Total clusters found in region {regional_client.region}: {len(self.clusters)}" + ) except Exception as error: logger.error( f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + logger.error( + f"Kafka - Error details in region {regional_client.region}: {str(error)}" + ) def _list_kafka_versions(self, regional_client): try: diff --git a/tests/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk_test.py b/tests/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk_test.py index 236da74917..3673c32717 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_encryption_at_rest_uses_cmk/kafka_cluster_encryption_at_rest_uses_cmk_test.py @@ -162,3 +162,64 @@ class Test_kafka_cluster_encryption_at_rest_uses_cmk: ) assert result[0].resource_tags == [] assert result[0].region == AWS_REGION_US_EAST_1 + + def test_kafka_cluster_serverless_encryption_at_rest(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + kms_client = MagicMock + kms_client.keys = [] + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + ), + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_cluster_encryption_at_rest_uses_cmk.kafka_cluster_encryption_at_rest_uses_cmk.kms_client", + new=kms_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_encryption_at_rest_uses_cmk.kafka_cluster_encryption_at_rest_uses_cmk import ( + kafka_cluster_encryption_at_rest_uses_cmk, + ) + + check = kafka_cluster_encryption_at_rest_uses_cmk() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and always has encryption at rest enabled by default." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_US_EAST_1 diff --git a/tests/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled_test.py b/tests/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled_test.py index 784d5ebff4..967c6740c0 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_enhanced_monitoring_enabled/kafka_cluster_enhanced_monitoring_enabled_test.py @@ -4,7 +4,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( Cluster, EncryptionInTransit, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_enhanced_monitoring_enabled: @@ -14,11 +14,11 @@ class Test_kafka_cluster_enhanced_monitoring_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -56,11 +56,11 @@ class Test_kafka_cluster_enhanced_monitoring_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -110,11 +110,11 @@ class Test_kafka_cluster_enhanced_monitoring_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -138,3 +138,57 @@ class Test_kafka_cluster_enhanced_monitoring_enabled: ) assert result[0].resource_tags == [] assert result[0].region == AWS_REGION_US_EAST_1 + + def test_kafka_cluster_serverless_enhanced_monitoring(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_enhanced_monitoring_enabled.kafka_cluster_enhanced_monitoring_enabled import ( + kafka_cluster_enhanced_monitoring_enabled, + ) + + check = kafka_cluster_enhanced_monitoring_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and always has enhanced monitoring enabled by default." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_US_EAST_1 diff --git a/tests/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled_test.py b/tests/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled_test.py index 78368530ea..a4b8165ec6 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_in_transit_encryption_enabled/kafka_cluster_in_transit_encryption_enabled_test.py @@ -4,7 +4,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( Cluster, EncryptionInTransit, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_in_transit_encryption_enabled: @@ -14,11 +14,11 @@ class Test_kafka_cluster_in_transit_encryption_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -56,11 +56,11 @@ class Test_kafka_cluster_in_transit_encryption_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -110,11 +110,11 @@ class Test_kafka_cluster_in_transit_encryption_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -164,11 +164,11 @@ class Test_kafka_cluster_in_transit_encryption_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -191,3 +191,57 @@ class Test_kafka_cluster_in_transit_encryption_enabled: == "arn:aws:kafka:us-east-1:123456789012:cluster/demo-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" ) assert result[0].region == AWS_REGION_US_EAST_1 + + def test_kafka_cluster_serverless_in_transit_encryption(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_in_transit_encryption_enabled.kafka_cluster_in_transit_encryption_enabled import ( + kafka_cluster_in_transit_encryption_enabled, + ) + + check = kafka_cluster_in_transit_encryption_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and always has encryption in transit enabled by default." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py b/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py index 392582b0ee..12459150df 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py @@ -4,7 +4,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( Cluster, EncryptionInTransit, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_is_public: @@ -14,11 +14,11 @@ class Test_kafka_cluster_is_public: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -56,11 +56,11 @@ class Test_kafka_cluster_is_public: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -110,11 +110,11 @@ class Test_kafka_cluster_is_public: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -138,3 +138,57 @@ class Test_kafka_cluster_is_public: assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] + + def test_kafka_cluster_serverless_public(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_is_public.kafka_cluster_is_public import ( + kafka_cluster_is_public, + ) + + check = kafka_cluster_is_public() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster serverless-cluster-1 is serverless and always private by default." + ) + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled_test.py b/tests/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled_test.py index c5d7f42205..651184f063 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_mutual_tls_authentication_enabled/kafka_cluster_mutual_tls_authentication_enabled_test.py @@ -4,7 +4,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( Cluster, EncryptionInTransit, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_mutual_tls_authentication_enabled: @@ -14,11 +14,11 @@ class Test_kafka_cluster_mutual_tls_authentication_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -56,11 +56,11 @@ class Test_kafka_cluster_mutual_tls_authentication_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -110,11 +110,11 @@ class Test_kafka_cluster_mutual_tls_authentication_enabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -138,3 +138,57 @@ class Test_kafka_cluster_mutual_tls_authentication_enabled: ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] + + def test_kafka_cluster_serverless_mutual_tls_authentication(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_mutual_tls_authentication_enabled.kafka_cluster_mutual_tls_authentication_enabled import ( + kafka_cluster_mutual_tls_authentication_enabled, + ) + + check = kafka_cluster_mutual_tls_authentication_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and always has TLS authentication enabled by default." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled_test.py b/tests/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled_test.py index 22a2c0eb71..17d01e5635 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_unrestricted_access_disabled/kafka_cluster_unrestricted_access_disabled_test.py @@ -4,7 +4,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( Cluster, EncryptionInTransit, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_unrestricted_access_disabled: @@ -14,11 +14,11 @@ class Test_kafka_cluster_unrestricted_access_disabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -56,11 +56,11 @@ class Test_kafka_cluster_unrestricted_access_disabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -110,11 +110,11 @@ class Test_kafka_cluster_unrestricted_access_disabled: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -138,3 +138,57 @@ class Test_kafka_cluster_unrestricted_access_disabled: ) assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] + + def test_kafka_cluster_serverless_unrestricted_access_disabled(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_unrestricted_access_disabled.kafka_cluster_unrestricted_access_disabled import ( + kafka_cluster_unrestricted_access_disabled, + ) + + check = kafka_cluster_unrestricted_access_disabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and always requires authentication by default." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version_test.py b/tests/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version_test.py index ac44f868e0..cfae707ad9 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_uses_latest_version/kafka_cluster_uses_latest_version_test.py @@ -5,7 +5,7 @@ from prowler.providers.aws.services.kafka.kafka_service import ( EncryptionInTransit, KafkaVersion, ) -from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider +from tests.providers.aws.utils import AWS_REGION_US_EAST_1 class Test_kafka_cluster_latest_version: @@ -15,11 +15,11 @@ class Test_kafka_cluster_latest_version: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -62,11 +62,11 @@ class Test_kafka_cluster_latest_version: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -121,11 +121,11 @@ class Test_kafka_cluster_latest_version: with ( patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_aws_provider([AWS_REGION_US_EAST_1]), + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, ), patch( - "prowler.providers.aws.services.kafka.kafka_service.Kafka", + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", new=kafka_client, ), ): @@ -149,3 +149,62 @@ class Test_kafka_cluster_latest_version: ) assert result[0].resource_tags == [] assert result[0].region == AWS_REGION_US_EAST_1 + + def test_kafka_cluster_serverless_uses_latest_version(self): + kafka_client = MagicMock + kafka_client.clusters = { + "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6": Cluster( + id="6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + name="serverless-cluster-1", + arn="arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + region=AWS_REGION_US_EAST_1, + tags=[], + state="ACTIVE", + kafka_version="SERVERLESS", + data_volume_kms_key_id="AWS_MANAGED", + encryption_in_transit=EncryptionInTransit( + client_broker="TLS", + in_cluster=True, + ), + tls_authentication=True, + public_access=False, + unauthentication_access=False, + enhanced_monitoring="DEFAULT", + ) + } + + kafka_client.kafka_versions = [ + KafkaVersion(version="1.0.0", status="DEPRECATED"), + KafkaVersion(version="2.8.0", status="ACTIVE"), + ] + + with ( + patch( + "prowler.providers.aws.services.kafka.kafka_service.Kafka", + new=kafka_client, + ), + patch( + "prowler.providers.aws.services.kafka.kafka_client.kafka_client", + new=kafka_client, + ), + ): + from prowler.providers.aws.services.kafka.kafka_cluster_uses_latest_version.kafka_cluster_uses_latest_version import ( + kafka_cluster_uses_latest_version, + ) + + check = kafka_cluster_uses_latest_version() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "Kafka cluster 'serverless-cluster-1' is serverless and AWS automatically manages the Kafka version." + ) + assert result[0].resource_id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert ( + result[0].resource_arn + == "arn:aws:kafka:us-east-1:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + ) + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_US_EAST_1 diff --git a/tests/providers/aws/services/kafka/kafka_service_test.py b/tests/providers/aws/services/kafka/kafka_service_test.py index a7767a0201..e041c4e125 100644 --- a/tests/providers/aws/services/kafka/kafka_service_test.py +++ b/tests/providers/aws/services/kafka/kafka_service_test.py @@ -13,47 +13,67 @@ make_api_call = botocore.client.BaseClient._make_api_call def mock_make_api_call(self, operation_name, kwarg): - if operation_name == "ListClusters": + if operation_name == "ListClustersV2": return { "ClusterInfoList": [ { - "BrokerNodeGroupInfo": { - "BrokerAZDistribution": "DEFAULT", - "ClientSubnets": ["subnet-cbfff283", "subnet-6746046b"], - "InstanceType": "kafka.m5.large", - "SecurityGroups": ["sg-f839b688"], - "StorageInfo": {"EbsStorageInfo": {"VolumeSize": 100}}, - }, + "ClusterType": "PROVISIONED", "ClusterArn": f"arn:aws:kafka:{AWS_REGION_US_EAST_1}:123456789012:cluster/demo-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5", "ClusterName": "demo-cluster-1", - "CreationTime": "2020-07-09T02:31:36.223000+00:00", - "CurrentBrokerSoftwareInfo": {"KafkaVersion": "2.2.1"}, - "CurrentVersion": "K3AEGXETSR30VB", - "EncryptionInfo": { - "EncryptionAtRest": { - "DataVolumeKMSKeyId": f"arn:aws:kms:{AWS_REGION_US_EAST_1}:123456789012:key/a7ca56d5-0768-4b64-a670-339a9fbef81c" - }, - "EncryptionInTransit": { - "ClientBroker": "TLS_PLAINTEXT", - "InCluster": True, - }, - }, - "ClientAuthentication": { - "Tls": {"CertificateAuthorityArnList": [], "Enabled": True}, - "Unauthenticated": {"Enabled": False}, - }, - "EnhancedMonitoring": "DEFAULT", - "OpenMonitoring": { - "Prometheus": { - "JmxExporter": {"EnabledInBroker": False}, - "NodeExporter": {"EnabledInBroker": False}, - } - }, - "NumberOfBrokerNodes": 2, "State": "ACTIVE", "Tags": {}, - "ZookeeperConnectString": f"z-2.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181,z-1.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181,z-3.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181", - } + "Provisioned": { + "BrokerNodeGroupInfo": { + "BrokerAZDistribution": "DEFAULT", + "ClientSubnets": ["subnet-cbfff283", "subnet-6746046b"], + "InstanceType": "kafka.m5.large", + "SecurityGroups": ["sg-f839b688"], + "StorageInfo": {"EbsStorageInfo": {"VolumeSize": 100}}, + "ConnectivityInfo": { + "PublicAccess": {"Type": "SERVICE_PROVIDED_EIPS"} + }, + }, + "CurrentBrokerSoftwareInfo": {"KafkaVersion": "2.2.1"}, + "CurrentVersion": "K3AEGXETSR30VB", + "EncryptionInfo": { + "EncryptionAtRest": { + "DataVolumeKMSKeyId": f"arn:aws:kms:{AWS_REGION_US_EAST_1}:123456789012:key/a7ca56d5-0768-4b64-a670-339a9fbef81c" + }, + "EncryptionInTransit": { + "ClientBroker": "TLS_PLAINTEXT", + "InCluster": True, + }, + }, + "ClientAuthentication": { + "Tls": {"CertificateAuthorityArnList": [], "Enabled": True}, + "Unauthenticated": {"Enabled": False}, + }, + "EnhancedMonitoring": "DEFAULT", + "OpenMonitoring": { + "Prometheus": { + "JmxExporter": {"EnabledInBroker": False}, + "NodeExporter": {"EnabledInBroker": False}, + } + }, + "NumberOfBrokerNodes": 2, + "ZookeeperConnectString": f"z-2.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181,z-1.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181,z-3.demo-cluster-1.xuy0sb.c5.kafka.{AWS_REGION_US_EAST_1}.amazonaws.com:2181", + }, + }, + { + "ClusterType": "SERVERLESS", + "ClusterArn": f"arn:aws:kafka:{AWS_REGION_US_EAST_1}:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6", + "ClusterName": "serverless-cluster-1", + "State": "ACTIVE", + "Tags": {}, + "Serverless": { + "VpcConfigs": [ + { + "SubnetIds": ["subnet-cbfff283", "subnet-6746046b"], + "SecurityGroups": ["sg-f839b688"], + } + ], + }, + }, ] } elif operation_name == "ListKafkaVersions": @@ -86,32 +106,53 @@ class TestKafkaService: assert kafka.__class__.__name__ == "Kafka" assert kafka.session.__class__.__name__ == "Session" assert kafka.audited_account == AWS_ACCOUNT_NUMBER - # Clusters assertions - assert len(kafka.clusters) == 1 - cluster_arn = f"arn:aws:kafka:{AWS_REGION_US_EAST_1}:123456789012:cluster/demo-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" - assert cluster_arn in kafka.clusters + + # Clusters assertions - should now include both provisioned and serverless + assert len(kafka.clusters) == 2 + + # Check provisioned cluster + provisioned_cluster_arn = f"arn:aws:kafka:{AWS_REGION_US_EAST_1}:123456789012:cluster/demo-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" + assert provisioned_cluster_arn in kafka.clusters + provisioned_cluster = kafka.clusters[provisioned_cluster_arn] + assert provisioned_cluster.id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" + assert provisioned_cluster.arn == provisioned_cluster_arn + assert provisioned_cluster.name == "demo-cluster-1" + assert provisioned_cluster.region == AWS_REGION_US_EAST_1 + assert provisioned_cluster.tags == [] + assert provisioned_cluster.state == "ACTIVE" + assert provisioned_cluster.kafka_version == "2.2.1" assert ( - kafka.clusters[cluster_arn].id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-5" - ) - assert kafka.clusters[cluster_arn].arn == cluster_arn - assert kafka.clusters[cluster_arn].name == "demo-cluster-1" - assert kafka.clusters[cluster_arn].region == AWS_REGION_US_EAST_1 - assert kafka.clusters[cluster_arn].tags == [] - assert kafka.clusters[cluster_arn].state == "ACTIVE" - assert kafka.clusters[cluster_arn].kafka_version == "2.2.1" - assert ( - kafka.clusters[cluster_arn].data_volume_kms_key_id + provisioned_cluster.data_volume_kms_key_id == f"arn:aws:kms:{AWS_REGION_US_EAST_1}:123456789012:key/a7ca56d5-0768-4b64-a670-339a9fbef81c" ) assert ( - kafka.clusters[cluster_arn].encryption_in_transit.client_broker - == "TLS_PLAINTEXT" + provisioned_cluster.encryption_in_transit.client_broker == "TLS_PLAINTEXT" ) - assert kafka.clusters[cluster_arn].encryption_in_transit.in_cluster - assert kafka.clusters[cluster_arn].enhanced_monitoring == "DEFAULT" - assert kafka.clusters[cluster_arn].tls_authentication - assert kafka.clusters[cluster_arn].public_access - assert not kafka.clusters[cluster_arn].unauthentication_access + assert provisioned_cluster.encryption_in_transit.in_cluster + assert provisioned_cluster.enhanced_monitoring == "DEFAULT" + assert provisioned_cluster.tls_authentication + assert provisioned_cluster.public_access + assert not provisioned_cluster.unauthentication_access + + # Check serverless cluster + serverless_cluster_arn = f"arn:aws:kafka:{AWS_REGION_US_EAST_1}:123456789012:cluster/serverless-cluster-1/6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert serverless_cluster_arn in kafka.clusters + serverless_cluster = kafka.clusters[serverless_cluster_arn] + assert serverless_cluster.id == "6357e0b2-0e6a-4b86-a0b4-70df934c2e31-6" + assert serverless_cluster.arn == serverless_cluster_arn + assert serverless_cluster.name == "serverless-cluster-1" + assert serverless_cluster.region == AWS_REGION_US_EAST_1 + assert serverless_cluster.tags == [] + assert serverless_cluster.state == "ACTIVE" + assert serverless_cluster.kafka_version == "SERVERLESS" + assert serverless_cluster.data_volume_kms_key_id == "AWS_MANAGED" + assert serverless_cluster.encryption_in_transit.client_broker == "TLS" + assert serverless_cluster.encryption_in_transit.in_cluster + assert serverless_cluster.enhanced_monitoring == "DEFAULT" + assert serverless_cluster.tls_authentication + assert not serverless_cluster.public_access + assert not serverless_cluster.unauthentication_access + # Kafka versions assertions assert len(kafka.kafka_versions) == 2 assert kafka.kafka_versions[0].version == "1.0.0" From 5b0365947f91f8b15155bcbc351431ea190c2b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Fri, 12 Sep 2025 09:56:36 +0200 Subject: [PATCH 6/6] feat: add first Prowler MCP server version (#8695) --- mcp_server/.gitignore | 151 ++++++ mcp_server/README.md | 88 ++++ mcp_server/prowler_mcp_server/__init__.py | 12 + mcp_server/prowler_mcp_server/main.py | 20 + .../prowler_hub/__init__.py | 3 + .../prowler_mcp_server/prowler_hub/server.py | 479 ++++++++++++++++++ mcp_server/prowler_mcp_server/server.py | 18 + mcp_server/pyproject.toml | 20 + 8 files changed, 791 insertions(+) create mode 100644 mcp_server/.gitignore create mode 100644 mcp_server/README.md create mode 100644 mcp_server/prowler_mcp_server/__init__.py create mode 100644 mcp_server/prowler_mcp_server/main.py create mode 100644 mcp_server/prowler_mcp_server/prowler_hub/__init__.py create mode 100644 mcp_server/prowler_mcp_server/prowler_hub/server.py create mode 100644 mcp_server/prowler_mcp_server/server.py create mode 100644 mcp_server/pyproject.toml diff --git a/mcp_server/.gitignore b/mcp_server/.gitignore new file mode 100644 index 0000000000..252bf7dad7 --- /dev/null +++ b/mcp_server/.gitignore @@ -0,0 +1,151 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +Pipfile.lock + +# poetry +poetry.lock + +# pdm +.pdm.toml +.pdm-python +pdm.lock + +# PEP 582 +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +.idea/ + +# VS Code +.vscode/ +.cursor/ + +# macOS +.DS_Store + +# uv +uv.lock diff --git a/mcp_server/README.md b/mcp_server/README.md new file mode 100644 index 0000000000..886e10b853 --- /dev/null +++ b/mcp_server/README.md @@ -0,0 +1,88 @@ +# Prowler MCP Server + +Access the entire Prowler ecosystem through the Model Context Protocol (MCP), the supported capabilities right now are: + +- Prowler Hub for checking the current covering in checks, fixers and compliance frameworks in Prowler. + +## Requirements + +- Python 3.12+ +- Network access to `https://hub.prowler.com` + +## Installation + +### From Sources + +It is needed to have [uv](https://docs.astral.sh/uv/) installed. + +```bash +git clone https://github.com/prowler-cloud/prowler.git +``` + +## Running + +After installation, start the MCP server via the console script: + +```bash +cd prowler/mcp_server +uv run prowler-mcp +``` + +Alternatively, you can run from wherever you want using `uvx` command: + +```bash +uvx /path/to/prowler/mcp_server/ +``` + +## Available Tools + +### Prowler Hub + +All tools are exposed under the `prowler_hub` prefix. + +- prowler_hub_get_check_filters: Return available filter values for checks (providers, services, severities, categories, compliances). Call this before `prowler_hub_get_checks` to build valid queries. +- prowler_hub_get_checks: List checks with option of advanced filtering. +- prowler_hub_search_checks: Full‑text search across check metadata. +- prowler_hub_get_compliance_frameworks: List/filter compliance frameworks. +- prowler_hub_search_compliance_frameworks: Full-text search across frameworks. +- prowler_hub_list_providers: List Prowler official providers and their services. +- prowler_hub_get_artifacts_count: Return total artifact count (checks + frameworks). + +## MCP Client Configuration + +Configure your MCP client to launch the server with the `uvx` command. Below is a generic snippet; consult your client's documentation for exact locations. + +```json +{ + "mcpServers": { + "prowler": { + "command": "uvx", + "args": ["/path/to/prowler/mcp_server/"] + } + } +} +``` + +### Claude Desktop (macOS/Windows) + +Add the server to Claude Desktop’s config file, then restart the app. + +- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` +- Windows: `%AppData%\Claude\claude_desktop_config.json` (e.g. `C:\\Users\\\\AppData\\Roaming\\Claude\\claude_desktop_config.json`) + +Example content to append/merge: + +```json +{ + "mcpServers": { + "prowler": { + "command": "uvx", + "args": ["/path/to/prowler/mcp_server/"] + } + } +} +``` + +## License + +This project follows the repository’s main license. See the [LICENSE](../LICENSE) file at the repository root. diff --git a/mcp_server/prowler_mcp_server/__init__.py b/mcp_server/prowler_mcp_server/__init__.py new file mode 100644 index 0000000000..91963cdca1 --- /dev/null +++ b/mcp_server/prowler_mcp_server/__init__.py @@ -0,0 +1,12 @@ +""" +Prowler MCP - Model Context Protocol server for Prowler ecosystem + +This package provides MCP tools for accessing: +- Prowler Hub: All security artifacts (detections, remediations and frameworks) supported by Prowler +""" + +__version__ = "0.1.0" +__author__ = "Prowler Team" +__email__ = "engineering@prowler.com" + +__all__ = ["__version__", "prowler_mcp_server"] diff --git a/mcp_server/prowler_mcp_server/main.py b/mcp_server/prowler_mcp_server/main.py new file mode 100644 index 0000000000..9519bd4c6b --- /dev/null +++ b/mcp_server/prowler_mcp_server/main.py @@ -0,0 +1,20 @@ +import asyncio +import sys +from prowler_mcp_server.server import setup_main_server, prowler_mcp_server + + +def main(): + """Main entry point for the MCP server.""" + try: + asyncio.run(setup_main_server()) + prowler_mcp_server.run() + except KeyboardInterrupt: + print("\nShutting down Prowler MCP server...") + sys.exit(0) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/mcp_server/prowler_mcp_server/prowler_hub/__init__.py b/mcp_server/prowler_mcp_server/prowler_hub/__init__.py new file mode 100644 index 0000000000..d67b34a7f8 --- /dev/null +++ b/mcp_server/prowler_mcp_server/prowler_hub/__init__.py @@ -0,0 +1,3 @@ +"""Prowler Hub module for MCP server.""" + +__all__ = ["prowler_hub_mcp"] diff --git a/mcp_server/prowler_mcp_server/prowler_hub/server.py b/mcp_server/prowler_mcp_server/prowler_hub/server.py new file mode 100644 index 0000000000..bd1a486e3e --- /dev/null +++ b/mcp_server/prowler_mcp_server/prowler_hub/server.py @@ -0,0 +1,479 @@ +""" +Prowler Hub MCP module + +Provides access to Prowler Hub API for security checks and compliance frameworks. +""" + +from typing import Optional, Any +import httpx +from fastmcp import FastMCP + +# Initialize FastMCP for Prowler Hub +hub_mcp_server = FastMCP("prowler-hub") + +# API base URL +BASE_URL = "https://hub.prowler.com/api" + +# HTTP client configuration +client = httpx.Client( + base_url=BASE_URL, timeout=30.0, headers={"Accept": "application/json"} +) + +# GitHub raw content base URL for Prowler checks +GITHUB_RAW_BASE = ( + "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/" + "prowler/providers" +) + +# Separate HTTP client for GitHub raw content +github_client = httpx.Client( + timeout=30.0, + headers={ + "Accept": "*/*", + "User-Agent": "prowler-mcp-server/1.0", + }, +) + + +def github_check_path(provider_id: str, check_id: str, suffix: str) -> str: + """Build the GitHub raw URL for a given check artifact suffix using provider + and check_id. + + Suffix examples: ".metadata.json", ".py", "_fixer.py" + """ + try: + service_id = check_id.split("_", 1)[0] + except IndexError: + service_id = check_id + return f"{GITHUB_RAW_BASE}/{provider_id}/services/{service_id}/{check_id}/{check_id}{suffix}" + + +@hub_mcp_server.tool() +async def get_check_filters() -> dict[str, Any]: + """ + Get available values for filtering for tool `get_checks`. Recommended to use before calling `get_checks` to get the available values for the filters. + + Returns: + Available filter options including providers, types, services, severities, + categories, and compliance frameworks with their respective counts + """ + try: + response = client.get("/check/filters") + response.raise_for_status() + filters = response.json() + + return {"filters": filters} + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +# Security Check Tools +@hub_mcp_server.tool() +async def get_checks( + providers: Optional[str] = None, + types: Optional[str] = None, + services: Optional[str] = None, + severities: Optional[str] = None, + categories: Optional[str] = None, + compliances: Optional[str] = None, + ids: Optional[str] = None, + fields: Optional[str] = "id,service,severity,title,description,risk", +) -> dict[str, Any]: + """ + List security Prowler Checks. The list can be filtered by the parameters defined for the tool. + It is recommended to use the tool `get_check_filters` to get the available values for the filters. + A not filtered request will return more than 1000 checks, so it is recommended to use the filters. + + Args: + providers: Filter by Prowler provider IDs. Example: "aws,azure". Use the tool `list_providers` to get the available providers IDs. + types: Filter by check types. + services: Filter by provider services IDs. Example: "s3,keyvault". Use the tool `list_providers` to get the available services IDs in a provider. + severities: Filter by severity levels. Example: "medium,high". Available values are "low", "medium", "high", "critical". + categories: Filter by categories. Example: "cluster-security,encryption". + compliances: Filter by compliance framework IDs. Example: "cis_4.0_aws,ens_rd2022_azure". + ids: Filter by specific check IDs. Example: "s3_bucket_level_public_access_block". + fields: Specify which fields from checks metadata to return (id is always included). Example: "id,title,description,risk". + Available values are "id", "title", "description", "provider", "type", "service", "subservice", "severity", "risk", "reference", "remediation", "services_required", "aws_arn_template", "notes", "categories", "default_value", "resource_type", "related_url", "depends_on", "related_to", "fixer". + The default parameters are "id,title,description". + If null, all fields will be returned. + + Returns: + List of security checks matching the filters. The structure is as follows: + { + "count": N, + "checks": [ + {"id": "check_id_1", "title": "check_title_1", "description": "check_description_1", ...}, + {"id": "check_id_2", "title": "check_title_2", "description": "check_description_2", ...}, + {"id": "check_id_3", "title": "check_title_3", "description": "check_description_3", ...}, + ... + ] + } + """ + params: dict[str, str] = {} + + if providers: + params["providers"] = providers + if types: + params["types"] = types + if services: + params["services"] = services + if severities: + params["severities"] = severities + if categories: + params["categories"] = categories + if compliances: + params["compliances"] = compliances + if ids: + params["ids"] = ids + if fields: + params["fields"] = fields + + try: + response = client.get("/check", params=params) + response.raise_for_status() + checks = response.json() + + checks_dict = {} + for check in checks: + check_data = {} + # Always include the id field as it's mandatory for the response structure + if "id" in check: + check_data["id"] = check["id"] + + # Include other requested fields + for field in fields.split(","): + if field != "id" and field in check: # Skip id since it's already added + check_data[field] = check[field] + checks_dict[check["id"]] = check_data + + return {"count": len(checks), "checks": checks_dict} + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +@hub_mcp_server.tool() +async def get_check_raw_metadata( + provider_id: str, + check_id: str, +) -> dict[str, Any]: + """ + Fetch the raw check metadata JSON, this is a low level version of the tool `get_checks`. + It is recommended to use the tool `get_checks` filtering about the `ids` parameter instead of using this tool. + + Args: + provider_id: Prowler provider ID (e.g., "aws", "azure"). + check_id: Prowler check ID (folder and base filename). + + Returns: + Raw metadata JSON as stored in Prowler. + """ + if provider_id and check_id: + url = github_check_path(provider_id, check_id, ".metadata.json") + try: + resp = github_client.get(url) + resp.raise_for_status() + return resp.json() + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + return { + "error": f"Check {check_id} not found in Prowler", + } + else: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return { + "error": f"Error fetching check {check_id} from Prowler: {str(e)}", + } + else: + return { + "error": "Provider ID and check ID are required", + } + + +@hub_mcp_server.tool() +async def get_check_code( + provider_id: str, + check_id: str, +) -> dict[str, Any]: + """ + Fetch the check implementation Python code from Prowler. + + Args: + provider_id: Prowler provider ID (e.g., "aws", "azure"). + check_id: Prowler check ID (e.g., "opensearch_service_domains_not_publicly_accessible"). + + Returns: + Dict with the code content as text. + """ + if provider_id and check_id: + url = github_check_path(provider_id, check_id, ".py") + try: + resp = github_client.get(url) + resp.raise_for_status() + return { + "content": resp.text, + } + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + return { + "error": f"Check {check_id} not found in Prowler", + } + else: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return { + "error": str(e), + } + else: + return { + "error": "Provider ID and check ID are required", + } + + +@hub_mcp_server.tool() +async def get_check_fixer( + provider_id: str, + check_id: str, +) -> dict[str, Any]: + """ + Fetch the check fixer Python code from Prowler, if it exists. + + Args: + provider_id: Prowler provider ID (e.g., "aws", "azure"). + check_id: Prowler check ID (e.g., "opensearch_service_domains_not_publicly_accessible"). + + Returns: + Dict with fixer content as text if present, existence flag. + """ + if provider_id and check_id: + url = github_check_path(provider_id, check_id, "_fixer.py") + try: + resp = github_client.get(url) + if resp.status_code == 404: + return { + "error": f"Fixer not found for check {check_id}", + } + resp.raise_for_status() + return { + "content": resp.text, + } + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + return { + "error": f"Check {check_id} not found in Prowler", + } + else: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return { + "error": str(e), + } + else: + return { + "error": "Provider ID and check ID are required", + } + + +@hub_mcp_server.tool() +async def search_checks(term: str) -> dict[str, Any]: + """ + Search the term across all text properties of check metadata. + + Args: + term: Search term to find in check titles, descriptions, and other text fields + + Returns: + List of checks matching the search term + """ + try: + response = client.get("/check/search", params={"term": term}) + response.raise_for_status() + checks = response.json() + + return { + "count": len(checks), + "checks": checks, + } + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +# Compliance Framework Tools +@hub_mcp_server.tool() +async def get_compliance_frameworks( + provider: Optional[str] = None, + fields: Optional[ + str + ] = "id,framework,provider,description,total_checks,total_requirements", +) -> dict[str, Any]: + """ + List and filter compliance frameworks. The list can be filtered by the parameters defined for the tool. + + Args: + provider: Filter by one Prowler provider ID. Example: "aws". Use the tool `list_providers` to get the available providers IDs. + fields: Specify which fields to return (id is always included). Example: "id,provider,description,version". + It is recommended to run with the default parameters because the full response is too large. + Available values are "id", "framework", "provider", "description", "total_checks", "total_requirements", "created_at", "updated_at". + The default parameters are "id,framework,provider,description,total_checks,total_requirements". + If null, all fields will be returned. + + Returns: + List of compliance frameworks. The structure is as follows: + { + "count": N, + "frameworks": { + "framework_id": { + "id": "framework_id", + "provider": "provider_id", + "description": "framework_description", + "version": "framework_version" + } + } + } + """ + params = {} + + if provider: + params["provider"] = provider + if fields: + params["fields"] = fields + + try: + response = client.get("/compliance", params=params) + response.raise_for_status() + frameworks = response.json() + + frameworks_dict = {} + for framework in frameworks: + framework_data = {} + # Always include the id field as it's mandatory for the response structure + if "id" in framework: + framework_data["id"] = framework["id"] + + # Include other requested fields + for field in fields.split(","): + if ( + field != "id" and field in framework + ): # Skip id since it's already added + framework_data[field] = framework[field] + frameworks_dict[framework["id"]] = framework_data + + return {"count": len(frameworks), "frameworks": frameworks_dict} + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +@hub_mcp_server.tool() +async def search_compliance_frameworks(term: str) -> dict[str, Any]: + """ + Search compliance frameworks by term. + + Args: + term: Search term to find in framework names and descriptions + + Returns: + List of compliance frameworks matching the search term + """ + try: + response = client.get("/compliance/search", params={"term": term}) + response.raise_for_status() + frameworks = response.json() + + return { + "count": len(frameworks), + "search_term": term, + "frameworks": frameworks, + } + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +# Provider Tools +@hub_mcp_server.tool() +async def list_providers() -> dict[str, Any]: + """ + Get all available Prowler providers and their associated services. + + Returns: + List of Prowler providers with their associated services. The structure is as follows: + { + "count": N, + "providers": { + "provider_id": { + "name": "provider_name", + "services": ["service_id_1", "service_id_2", "service_id_3", ...] + } + } + } + """ + try: + response = client.get("/providers") + response.raise_for_status() + providers = response.json() + + providers_dict = {} + for provider in providers: + providers_dict[provider["id"]] = { + "name": provider.get("name", ""), + "services": provider.get("services", []), + } + + return {"count": len(providers), "providers": providers_dict} + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} + + +# Analytics Tools +@hub_mcp_server.tool() +async def get_artifacts_count() -> dict[str, Any]: + """ + Get total count of security artifacts (checks + compliance frameworks). + + Returns: + Total number of artifacts in the Prowler Hub. + """ + try: + response = client.get("/n_artifacts") + response.raise_for_status() + data = response.json() + + return { + "total_artifacts": data.get("n", 0), + "details": "Total count includes both security checks and compliance frameworks", + } + except httpx.HTTPStatusError as e: + return { + "error": f"HTTP error {e.response.status_code}: {e.response.text}", + } + except Exception as e: + return {"error": str(e)} diff --git a/mcp_server/prowler_mcp_server/server.py b/mcp_server/prowler_mcp_server/server.py new file mode 100644 index 0000000000..ce55ff68aa --- /dev/null +++ b/mcp_server/prowler_mcp_server/server.py @@ -0,0 +1,18 @@ +from fastmcp import FastMCP + + +# Initialize main Prowler MCP server +prowler_mcp_server = FastMCP("prowler-mcp-server") + + +async def setup_main_server(): + """Set up the main Prowler MCP server with all available integrations.""" + + # Import Prowler Hub tools with prowler_hub_ prefix + try: + from prowler_mcp_server.prowler_hub.server import hub_mcp_server + + await prowler_mcp_server.import_server(hub_mcp_server, prefix="prowler_hub") + except Exception: + # TODO: Add error logging + pass diff --git a/mcp_server/pyproject.toml b/mcp_server/pyproject.toml new file mode 100644 index 0000000000..5dfdfc8f5d --- /dev/null +++ b/mcp_server/pyproject.toml @@ -0,0 +1,20 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "prowler-mcp" +version = "0.1.0" +description = "MCP server for Prowler ecosystem" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=2.11.3", + "httpx>=0.27.0", +] + +[project.scripts] +prowler-mcp = "prowler_mcp_server.main:main" + +[tool.uv] +package = true \ No newline at end of file