diff --git a/.gitignore b/.gitignore index 925f48e..8067e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -166,6 +166,12 @@ Thumbs.db !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json +.cursorrules +.cursorrules/* +!.cursorrules/.gitignore +.cursor/* +.cursor/*/* +.cursor # Turborepo cache (if you introduce turbo later) .turbo/ diff --git a/bandit-runner-app/package.json b/bandit-runner-app/package.json index 51e1567..30df9be 100644 --- a/bandit-runner-app/package.json +++ b/bandit-runner-app/package.json @@ -15,6 +15,8 @@ "@icons-pack/react-simple-icons": "^13.8.0", "@opennextjs/cloudflare": "^1.3.0", "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-scroll-area": "^1.2.10", diff --git a/bandit-runner-app/pnpm-lock.yaml b/bandit-runner-app/pnpm-lock.yaml index 71e2d71..e917648 100644 --- a/bandit-runner-app/pnpm-lock.yaml +++ b/bandit-runner-app/pnpm-lock.yaml @@ -17,6 +17,12 @@ importers: '@radix-ui/react-alert-dialog': specifier: ^1.1.15 version: 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-avatar': + specifier: ^1.1.10 + version: 1.1.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-collapsible': + specifier: ^1.1.12 + version: 1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-dialog': specifier: ^1.1.15 version: 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -1219,6 +1225,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-avatar@1.1.10': + resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collapsible@1.1.12': + resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-collection@1.1.7': resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: @@ -1504,6 +1536,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-is-hydrated@0.1.0': + resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-layout-effect@1.1.1': resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: @@ -4548,6 +4589,11 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} @@ -6308,6 +6354,35 @@ snapshots: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) + '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.2.2 + '@types/react-dom': 19.2.1(@types/react@19.2.2) + + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.2.2 + '@types/react-dom': 19.2.1(@types/react@19.2.2) + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.1.0) @@ -6591,6 +6666,13 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.2)(react@19.1.0)': + dependencies: + react: 19.1.0 + use-sync-external-store: 1.6.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.2.2 + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.2)(react@19.1.0)': dependencies: react: 19.1.0 @@ -10466,6 +10548,10 @@ snapshots: dependencies: react: 19.1.0 + use-sync-external-store@1.6.0(react@19.1.0): + dependencies: + react: 19.1.0 + utils-merge@1.0.1: {} uuid@9.0.1: {} diff --git a/bandit-runner-app/src/app/globals.css b/bandit-runner-app/src/app/globals.css index 4a91207..091ead3 100644 --- a/bandit-runner-app/src/app/globals.css +++ b/bandit-runner-app/src/app/globals.css @@ -3,180 +3,165 @@ @custom-variant dark (&:is(.dark *)); +:root { + --background: oklch(0.98 0 0); + --foreground: oklch(0.15 0 0); + --card: oklch(0.99 0 0); + --card-foreground: oklch(0.15 0 0); + --popover: oklch(0.99 0 0); + --popover-foreground: oklch(0.15 0 0); + --primary: oklch(0.35 0.15 250); + --primary-foreground: oklch(0.98 0 0); + --secondary: oklch(0.92 0 0); + --secondary-foreground: oklch(0.15 0 0); + --muted: oklch(0.94 0 0); + --muted-foreground: oklch(0.50 0 0); + --accent: oklch(0.88 0.08 250); + --accent-foreground: oklch(0.25 0.15 250); + --destructive: oklch(0.55 0.22 25); + --destructive-foreground: oklch(0.98 0 0); + --border: oklch(0.88 0 0); + --input: oklch(0.92 0 0); + --ring: oklch(0.35 0.15 250); + --chart-1: oklch(0.81 0.17 75.35); + --chart-2: oklch(0.55 0.22 264.53); + --chart-3: oklch(0.72 0 0); + --chart-4: oklch(0.92 0 0); + --chart-5: oklch(0.56 0 0); + --sidebar: oklch(0.99 0 0); + --sidebar-foreground: oklch(0.15 0 0); + --sidebar-primary: oklch(0.35 0.15 250); + --sidebar-primary-foreground: oklch(0.98 0 0); + --sidebar-accent: oklch(0.92 0 0); + --sidebar-accent-foreground: oklch(0.15 0 0); + --sidebar-border: oklch(0.92 0 0); + --sidebar-ring: oklch(0.35 0.15 250); + --font-sans: Geist, sans-serif; + --font-serif: Georgia, serif; + --font-mono: Geist Mono, monospace; + --radius: 0.5rem; + --shadow-x: 0px; + --shadow-y: 1px; + --shadow-blur: 2px; + --shadow-spread: 0px; + --shadow-opacity: 0.18; + --shadow-color: hsl(0 0% 0%); + --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09); + --shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09); + --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18); + --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18); + --shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18); + --shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18); + --shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18); + --shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45); + --tracking-normal: 0em; + --spacing: 0.25rem; +} + +.dark { + --background: oklch(0.08 0.01 250); + --foreground: oklch(0.90 0.05 200); + --card: oklch(0.12 0.01 250); + --card-foreground: oklch(0.90 0.05 200); + --popover: oklch(0.14 0.01 250); + --popover-foreground: oklch(0.90 0.05 200); + --primary: oklch(0.70 0.15 195); + --primary-foreground: oklch(0.08 0.01 250); + --secondary: oklch(0.22 0.01 250); + --secondary-foreground: oklch(0.90 0.05 200); + --muted: oklch(0.20 0.01 250); + --muted-foreground: oklch(0.55 0.03 200); + --accent: oklch(0.28 0.05 250); + --accent-foreground: oklch(0.75 0.15 180); + --destructive: oklch(0.60 0.20 25); + --destructive-foreground: oklch(0.95 0 0); + --border: oklch(0.24 0.02 250); + --input: oklch(0.28 0.02 250); + --ring: oklch(0.70 0.15 195); + --chart-1: oklch(0.81 0.17 75.35); + --chart-2: oklch(0.58 0.21 260.84); + --chart-3: oklch(0.56 0 0); + --chart-4: oklch(0.44 0 0); + --chart-5: oklch(0.92 0 0); + --sidebar: oklch(0.12 0.01 250); + --sidebar-foreground: oklch(0.90 0.05 200); + --sidebar-primary: oklch(0.70 0.15 195); + --sidebar-primary-foreground: oklch(0.08 0.01 250); + --sidebar-accent: oklch(0.28 0.05 250); + --sidebar-accent-foreground: oklch(0.75 0.15 180); + --sidebar-border: oklch(0.24 0.02 250); + --sidebar-ring: oklch(0.70 0.15 195); + --font-sans: Geist, sans-serif; + --font-serif: Georgia, serif; + --font-mono: Geist Mono, monospace; + --radius: 0.5rem; + --shadow-x: 0px; + --shadow-y: 1px; + --shadow-blur: 2px; + --shadow-spread: 0px; + --shadow-opacity: 0.18; + --shadow-color: hsl(0 0% 0%); + --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09); + --shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09); + --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18); + --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18); + --shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18); + --shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18); + --shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18); + --shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45); +} + @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); - --font-sans: 'JetBrains Mono', monospace; - --font-mono: 'JetBrains Mono', monospace; - --font-serif: 'JetBrains Mono', monospace; - --radius: 0rem; - --tracking-tighter: calc(var(--tracking-normal) - 0.05em); - --tracking-tight: calc(var(--tracking-normal) - 0.025em); - --tracking-wide: calc(var(--tracking-normal) + 0.025em); - --tracking-wider: calc(var(--tracking-normal) + 0.05em); - --tracking-widest: calc(var(--tracking-normal) + 0.1em); - --tracking-normal: var(--tracking-normal); - --shadow-2xl: var(--shadow-2xl); - --shadow-xl: var(--shadow-xl); - --shadow-lg: var(--shadow-lg); - --shadow-md: var(--shadow-md); - --shadow: var(--shadow); - --shadow-sm: var(--shadow-sm); - --shadow-xs: var(--shadow-xs); - --shadow-2xs: var(--shadow-2xs); - --spacing: var(--spacing); - --letter-spacing: var(--letter-spacing); - --shadow-offset-y: var(--shadow-offset-y); - --shadow-offset-x: var(--shadow-offset-x); - --shadow-spread: var(--shadow-spread); - --shadow-blur: var(--shadow-blur); - --shadow-opacity: var(--shadow-opacity); - --color-shadow-color: var(--shadow-color); - --color-destructive-foreground: var(--destructive-foreground); - --color-sidebar-ring: var(--sidebar-ring); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar: var(--sidebar); - --color-chart-5: var(--chart-5); - --color-chart-4: var(--chart-4); - --color-chart-3: var(--chart-3); - --color-chart-2: var(--chart-2); - --color-chart-1: var(--chart-1); - --color-ring: var(--ring); - --color-input: var(--input); - --color-border: var(--border); - --color-destructive: var(--destructive); - --color-accent-foreground: var(--accent-foreground); - --color-accent: var(--accent); - --color-muted-foreground: var(--muted-foreground); - --color-muted: var(--muted); - --color-secondary-foreground: var(--secondary-foreground); - --color-secondary: var(--secondary); - --color-primary-foreground: var(--primary-foreground); - --color-primary: var(--primary); - --color-popover-foreground: var(--popover-foreground); - --color-popover: var(--popover); - --color-card-foreground: var(--card-foreground); --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + + --font-sans: var(--font-sans); + --font-mono: var(--font-mono); + --font-serif: var(--font-serif); + --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); -} -:root { - --radius: 0rem; - --background: oklch(0 0 0); - --foreground: oklch(0.8664 0.2948 142.4953); - --card: oklch(0.2178 0 0); - --card-foreground: oklch(0.8664 0.2948 142.4953); - --popover: oklch(0.1448 0 0); - --popover-foreground: oklch(0.8664 0.2948 142.4953); - --primary: oklch(0.7323 0.2492 142.4953); - --primary-foreground: oklch(0 0 0); - --secondary: oklch(0.5430 0.1848 142.4953); - --secondary-foreground: oklch(1.0000 0 0); - --muted: oklch(0.2782 0.0947 142.4953); - --muted-foreground: oklch(0.6394 0.2176 142.4953); - --accent: oklch(0.3895 0.1325 142.4953); - --accent-foreground: oklch(0.8664 0.2948 142.4953); - --destructive: oklch(0.6280 0.2577 29.2339); - --border: oklch(0.3350 0.1140 142.4953); - --input: oklch(0.1448 0 0); - --ring: oklch(0.8664 0.2948 142.4953); - --chart-1: oklch(0.8664 0.2948 142.4953); - --chart-2: oklch(0.6863 0.2335 142.4953); - --chart-3: oklch(0.4932 0.1678 142.4953); - --chart-4: oklch(0.3895 0.1325 142.4953); - --chart-5: oklch(0.2782 0.0947 142.4953); - --sidebar: oklch(0.1149 0 0); - --sidebar-foreground: oklch(0.8664 0.2948 142.4953); - --sidebar-primary: oklch(0.7323 0.2492 142.4953); - --sidebar-primary-foreground: oklch(1.0000 0 0); - --sidebar-accent: oklch(0.5430 0.1848 142.4953); - --sidebar-accent-foreground: oklch(0.8664 0.2948 142.4953); - --sidebar-border: oklch(0.3350 0.1140 142.4953); - --sidebar-ring: oklch(0.8664 0.2948 142.4953); - --destructive-foreground: oklch(1.0000 0 0); - --font-sans: 'JetBrains Mono', monospace; - --font-serif: 'JetBrains Mono', monospace; - --font-mono: 'JetBrains Mono', monospace; - --shadow-color: #00ff00; - --shadow-opacity: 0.2; - --shadow-blur: 0.2rem; - --shadow-spread: 0rem; - --shadow-offset-x: 0rem; - --shadow-offset-y: 0.1rem; - --letter-spacing: 0.025em; - --spacing: 0.25rem; - --shadow-2xs: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.10); - --shadow-xs: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.10); - --shadow-sm: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 1px 2px -1px hsl(120 100% 50% / 0.20); - --shadow: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 1px 2px -1px hsl(120 100% 50% / 0.20); - --shadow-md: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 2px 4px -1px hsl(120 100% 50% / 0.20); - --shadow-lg: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 4px 6px -1px hsl(120 100% 50% / 0.20); - --shadow-xl: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 8px 10px -1px hsl(120 100% 50% / 0.20); - --shadow-2xl: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.50); - --tracking-normal: 0.025em; -} - -.dark { - --background: oklch(0 0 0); - --foreground: oklch(1.0000 0 0); - --card: oklch(0.1822 0 0); - --card-foreground: oklch(0.9706 0.0017 67.8024); - --popover: oklch(0.1448 0 0); - --popover-foreground: oklch(0.9706 0.0017 67.8024); - --primary: oklch(1.0000 0 0); - --primary-foreground: oklch(0 0 0); - --secondary: oklch(0.9706 0.0017 67.8024); - --secondary-foreground: oklch(0 0 0); - --muted: oklch(0.3979 0 0); - --muted-foreground: oklch(0.8975 0.0042 91.4501); - --accent: oklch(0.6829 0.0045 91.4665); - --accent-foreground: oklch(1.0000 0 0); - --destructive: oklch(0.6280 0.2577 29.2339); - --border: oklch(0.4794 0.0129 297.3461); - --input: oklch(0.1448 0 0); - --ring: oklch(1.0000 0 0); - --chart-1: oklch(0.8664 0.2948 142.4953); - --chart-2: oklch(0.6863 0.2335 142.4953); - --chart-3: oklch(0.4932 0.1678 142.4953); - --chart-4: oklch(0.3895 0.1325 142.4953); - --chart-5: oklch(0.2782 0.0947 142.4953); - --sidebar: oklch(0.1149 0 0); - --sidebar-foreground: oklch(0.8664 0.2948 142.4953); - --sidebar-primary: oklch(0.7323 0.2492 142.4953); - --sidebar-primary-foreground: oklch(1.0000 0 0); - --sidebar-accent: oklch(0.5430 0.1848 142.4953); - --sidebar-accent-foreground: oklch(0.8664 0.2948 142.4953); - --sidebar-border: oklch(0.3350 0.1140 142.4953); - --sidebar-ring: oklch(0.8664 0.2948 142.4953); - --destructive-foreground: oklch(1.0000 0 0); - --radius: 0rem; - --font-sans: 'JetBrains Mono', monospace; - --font-serif: 'JetBrains Mono', monospace; - --font-mono: 'JetBrains Mono', monospace; - --shadow-color: #00ff00; - --shadow-opacity: 0.2; - --shadow-blur: 0.2rem; - --shadow-spread: 0rem; - --shadow-offset-x: 0rem; - --shadow-offset-y: 0.1rem; - --letter-spacing: 0.025em; - --spacing: 0.25rem; - --shadow-2xs: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.10); - --shadow-xs: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.10); - --shadow-sm: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 1px 2px -1px hsl(120 100% 50% / 0.20); - --shadow: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 1px 2px -1px hsl(120 100% 50% / 0.20); - --shadow-md: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 2px 4px -1px hsl(120 100% 50% / 0.20); - --shadow-lg: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 4px 6px -1px hsl(120 100% 50% / 0.20); - --shadow-xl: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.20), 0rem 8px 10px -1px hsl(120 100% 50% / 0.20); - --shadow-2xl: 0rem 0.1rem 0.2rem 0rem hsl(120 100% 50% / 0.50); + --shadow-2xs: var(--shadow-2xs); + --shadow-xs: var(--shadow-xs); + --shadow-sm: var(--shadow-sm); + --shadow: var(--shadow); + --shadow-md: var(--shadow-md); + --shadow-lg: var(--shadow-lg); + --shadow-xl: var(--shadow-xl); + --shadow-2xl: var(--shadow-2xl); } @layer base { @@ -187,4 +172,30 @@ @apply bg-background text-foreground; letter-spacing: var(--tracking-normal); } + + @keyframes scan-lines { + 0% { + transform: translateY(0); + } + 100% { + transform: translateY(4px); + } + } + + @keyframes cursor-blink { + 0%, 49% { + opacity: 1; + } + 50%, 100% { + opacity: 0; + } + } + + .animate-scan-lines { + animation: scan-lines 0.1s linear infinite; + } + + .animate-cursor-blink { + animation: cursor-blink 1s step-end infinite; + } } \ No newline at end of file diff --git a/bandit-runner-app/src/app/layout.tsx b/bandit-runner-app/src/app/layout.tsx index f7fa87e..d61a967 100644 --- a/bandit-runner-app/src/app/layout.tsx +++ b/bandit-runner-app/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { ThemeProvider } from "@/components/theme-provider"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -13,8 +14,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Bandit Runner", + description: "Security Automation Console", }; export default function RootLayout({ @@ -23,11 +24,18 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + - {children} + + {children} + ); diff --git a/bandit-runner-app/src/app/page.tsx b/bandit-runner-app/src/app/page.tsx index a932894..b37a5c5 100644 --- a/bandit-runner-app/src/app/page.tsx +++ b/bandit-runner-app/src/app/page.tsx @@ -1,103 +1,5 @@ -import Image from "next/image"; +import { TerminalChatInterface } from "@/components/terminal-chat-interface" export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.tsx - - . -
  2. -
  3. - Save and see your changes instantly. -
  4. -
- -
- - Vercel logomark - Deploy now - - - Read our docs - -
-
- -
- ); + return } diff --git a/bandit-runner-app/src/components/retro-icons.tsx b/bandit-runner-app/src/components/retro-icons.tsx new file mode 100644 index 0000000..0d64172 --- /dev/null +++ b/bandit-runner-app/src/components/retro-icons.tsx @@ -0,0 +1,117 @@ +export function TerminalIcon({ className }: { className?: string }) { + return ( + + + + + + + ) +} + +export function BotIcon({ className }: { className?: string }) { + return ( + + + + + + + + + + + ) +} + +export function DatabaseIcon({ className }: { className?: string }) { + return ( + + + + + + ) +} + +export function SecurityIcon({ className }: { className?: string }) { + return ( + + + + + ) +} + +export function GitBranchIcon({ className }: { className?: string }) { + return ( + + + + + + + ) +} + +export function ServerIcon({ className }: { className?: string }) { + return ( + + + + + + + + + ) +} + diff --git a/bandit-runner-app/src/components/terminal-chat-interface.tsx b/bandit-runner-app/src/components/terminal-chat-interface.tsx new file mode 100644 index 0000000..ecf022a --- /dev/null +++ b/bandit-runner-app/src/components/terminal-chat-interface.tsx @@ -0,0 +1,416 @@ +"use client" + +import type React from "react" +import { useState, useRef, useEffect } from "react" +import { Github } from "lucide-react" +import { Input } from "@/components/ui/shadcn-io/input" +import { ScrollArea } from "@/components/ui/shadcn-io/scroll-area" +import { ThemeToggle } from "@/components/theme-toggle" +import { SecurityIcon } from "@/components/retro-icons" +import { cn } from "@/lib/utils" + +interface TerminalLine { + type: "input" | "output" | "error" + content: string + timestamp: Date +} + +interface ChatMessage { + type: "user" | "agent" | "typing" + content: string + timestamp: Date +} + +const SCAN_LINES_OVERLAY = + "absolute inset-0 pointer-events-none bg-[linear-gradient(transparent_50%,hsl(var(--primary)/0.03)_50%)] bg-[length:100%_4px] animate-scan-lines" + +const GRID_PATTERN = + "absolute inset-0 pointer-events-none opacity-[0.015] bg-[linear-gradient(hsl(var(--primary))_1px,transparent_1px),linear-gradient(90deg,hsl(var(--primary))_1px,transparent_1px)] bg-[size:20px_20px]" + +export function TerminalChatInterface() { + const [terminalLines, setTerminalLines] = useState([ + { type: "output", content: "Bandit Runner Console v1.0", timestamp: new Date() }, + { type: "output", content: "System initialized. Ready for commands.", timestamp: new Date() }, + { type: "output", content: "", timestamp: new Date() }, + ]) + const [chatMessages, setChatMessages] = useState([ + { type: "agent", content: "Agent ready. Awaiting commands...", timestamp: new Date() }, + ]) + const [currentCommand, setCurrentCommand] = useState("") + const [chatInput, setChatInput] = useState("") + const [commandHistory, setCommandHistory] = useState([]) + const [historyIndex, setHistoryIndex] = useState(-1) + const [isTyping, setIsTyping] = useState(false) + const [sessionTime, setSessionTime] = useState("") + const [focusedPanel, setFocusedPanel] = useState<"terminal" | "chat">("terminal") + const [mounted, setMounted] = useState(false) + + const terminalEndRef = useRef(null) + const chatEndRef = useRef(null) + const terminalInputRef = useRef(null) + const chatInputRef = useRef(null) + + useEffect(() => { + setMounted(true) + setSessionTime(new Date().toLocaleTimeString()) + terminalInputRef.current?.focus() + }, []) + + useEffect(() => { + terminalEndRef.current?.scrollIntoView({ behavior: "smooth" }) + }, [terminalLines]) + + useEffect(() => { + chatEndRef.current?.scrollIntoView({ behavior: "smooth" }) + }, [chatMessages]) + + const formatTimestamp = (date: Date) => { + return date.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" }) + } + + const handleCommandSubmit = (e: React.FormEvent) => { + e.preventDefault() + if (!currentCommand.trim()) return + + const command = currentCommand.trim() + setCommandHistory((prev) => [...prev, command]) + setHistoryIndex(-1) + + setTerminalLines((prev) => [ + ...prev, + { type: "input", content: `$ ${command}`, timestamp: new Date() }, + ]) + + setTimeout(() => { + setTerminalLines((prev) => [ + ...prev, + { + type: "output", + content: `Executing: ${command}...`, + timestamp: new Date(), + }, + { + type: "output", + content: `Command completed successfully.`, + timestamp: new Date(), + }, + { type: "output", content: "", timestamp: new Date() }, + ]) + }, 100) + + setCurrentCommand("") + } + + const handleChatSubmit = (e: React.FormEvent) => { + e.preventDefault() + if (!chatInput.trim()) return + + const message = chatInput.trim() + setChatMessages((prev) => [ + ...prev, + { + type: "user", + content: message, + timestamp: new Date(), + }, + ]) + + setChatInput("") + setIsTyping(true) + + setTimeout(() => { + setIsTyping(false) + setChatMessages((prev) => [ + ...prev, + { + type: "agent", + content: `Processing: "${message}"`, + timestamp: new Date(), + }, + ]) + }, 1500) + } + + const handleCommandKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "ArrowUp") { + e.preventDefault() + if (commandHistory.length === 0) return + const newIndex = historyIndex === -1 ? commandHistory.length - 1 : Math.max(0, historyIndex - 1) + setHistoryIndex(newIndex) + setCurrentCommand(commandHistory[newIndex]) + } else if (e.key === "ArrowDown") { + e.preventDefault() + if (historyIndex === -1) return + const newIndex = historyIndex + 1 + if (newIndex >= commandHistory.length) { + setHistoryIndex(-1) + setCurrentCommand("") + } else { + setHistoryIndex(newIndex) + setCurrentCommand(commandHistory[newIndex]) + } + } else if (e.key === "Escape") { + setFocusedPanel("chat") + chatInputRef.current?.focus() + } + } + + const handleChatKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Escape") { + setFocusedPanel("terminal") + terminalInputRef.current?.focus() + } + } + + useEffect(() => { + const handleGlobalKeyDown = (e: KeyboardEvent) => { + if (e.key === "j" && e.ctrlKey) { + e.preventDefault() + setFocusedPanel("chat") + chatInputRef.current?.focus() + } else if (e.key === "k" && e.ctrlKey) { + e.preventDefault() + setFocusedPanel("terminal") + terminalInputRef.current?.focus() + } + } + + window.addEventListener("keydown", handleGlobalKeyDown) + return () => window.removeEventListener("keydown", handleGlobalKeyDown) + }, []) + + return ( +
+
+ {/* Header with corner accents */} +
+ {/* Corner brackets */} +
+
+
+
+ +
+
+
+
+ +
+
+ BANDIT RUNNER +
+
+ Security Automation Console +
+
+
+
+ {mounted && ( +
+ SESSION + {sessionTime} +
+ )} +
+
+ ONLINE +
+ + + + +
+
+
+
+ + {/* Main content area */} +
+ {/* Terminal Panel */} +
+ {/* Corner accents */} +
+
+ +
+
+
+ + {/* Header */} +
+
+
+ TERMINAL +
+
+
+
+
+
+
+ + {/* Terminal content */} + +
+ {terminalLines.map((line, idx) => ( +
+ {line.content && ( + <> + + {formatTimestamp(line.timestamp)} + + {line.content} + + )} +
+ ))} +
+
+ + + {/* Input area */} +
+
+
+
+ $ +
+ setCurrentCommand(e.target.value)} + onKeyDown={handleCommandKeyDown} + placeholder="enter command..." + className="flex-1 bg-transparent border-0 text-foreground placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0 font-mono text-sm h-6 px-0 caret-primary" + /> + +
+ + {/* Footer */} +
+
+ user@bandit-runner + ↑↓ history • ESC switch panels +
+
+
+
+ + {/* Agent Panel */} +
+ {/* Corner accents */} +
+
+ +
+
+
+ + {/* Header */} +
+
+
+ AGENT +
+
+
+
+
+
+ + {/* Messages */} + +
+ {chatMessages.map((msg, idx) => ( +
+
+ + {formatTimestamp(msg.timestamp)} + +
+ + {msg.type === "user" ? "USER" : "AGENT"} + +
+
+ {msg.content} +
+
+ ))} + {isTyping && ( +
+
+ + {formatTimestamp(new Date())} + +
+ + AGENT + +
+
+ Processing + +
+
+ )} +
+
+ + + {/* Input area */} +
+
+
+
+ +
+ setChatInput(e.target.value)} + onKeyDown={handleChatKeyDown} + placeholder="message agent..." + className="flex-1 bg-transparent border-0 text-foreground placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0 font-mono text-sm h-6 px-0 caret-accent-foreground" + /> + +
+ + {/* Footer */} +
+
+ Ctrl+K/J nav + DeepSeek-V3 +
+
+
+
+
+
+
+ ) +} diff --git a/bandit-runner-app/src/components/theme-provider.tsx b/bandit-runner-app/src/components/theme-provider.tsx new file mode 100644 index 0000000..02414a7 --- /dev/null +++ b/bandit-runner-app/src/components/theme-provider.tsx @@ -0,0 +1,12 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" + +export function ThemeProvider({ + children, + ...props +}: React.ComponentProps) { + return {children} +} + diff --git a/bandit-runner-app/src/components/theme-toggle.tsx b/bandit-runner-app/src/components/theme-toggle.tsx new file mode 100644 index 0000000..9e80e29 --- /dev/null +++ b/bandit-runner-app/src/components/theme-toggle.tsx @@ -0,0 +1,40 @@ +"use client" + +import * as React from "react" +import { Moon, Sun } from "lucide-react" +import { useTheme } from "next-themes" + +export function ThemeToggle() { + const { theme, setTheme } = useTheme() + const [mounted, setMounted] = React.useState(false) + + React.useEffect(() => { + setMounted(true) + }, []) + + if (!mounted) { + return ( + + ) + } + + return ( + + ) +} + diff --git a/bandit-runner-app/src/components/ui/shadcn-io/ai/code-block.tsx b/bandit-runner-app/src/components/ui/shadcn-io/ai/code-block.tsx index 2b0a5a5..9f417ba 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/ai/code-block.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/ai/code-block.tsx @@ -1,7 +1,7 @@ 'use client'; -import { Button } from '@repo/shadcn-ui/components/ui/button'; -import { cn } from '@repo/shadcn-ui/lib/utils'; +import { Button } from '@/components/ui/shadcn-io/button'; +import { cn } from '@/lib/utils'; import { CheckIcon, CopyIcon } from 'lucide-react'; import type { ComponentProps, HTMLAttributes, ReactNode } from 'react'; import { createContext, useContext, useState } from 'react'; diff --git a/bandit-runner-app/src/components/ui/shadcn-io/ai/message.tsx b/bandit-runner-app/src/components/ui/shadcn-io/ai/message.tsx index 2dcf3fe..94c462f 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/ai/message.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/ai/message.tsx @@ -2,8 +2,8 @@ import { Avatar, AvatarFallback, AvatarImage, -} from '@repo/shadcn-ui/components/ui/avatar'; -import { cn } from '@repo/shadcn-ui/lib/utils'; +} from '@/components/ui/shadcn-io/avatar'; +import { cn } from '@/lib/utils'; import type { UIMessage } from 'ai'; import type { ComponentProps, HTMLAttributes } from 'react'; diff --git a/bandit-runner-app/src/components/ui/shadcn-io/ai/reasoning.tsx b/bandit-runner-app/src/components/ui/shadcn-io/ai/reasoning.tsx index 7c63018..c9e8512 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/ai/reasoning.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/ai/reasoning.tsx @@ -5,8 +5,8 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from '@repo/shadcn-ui/components/ui/collapsible'; -import { cn } from '@repo/shadcn-ui/lib/utils'; +} from '@/components/ui/shadcn-io/collapsible'; +import { cn } from '@/lib/utils'; import { BrainIcon, ChevronDownIcon } from 'lucide-react'; import type { ComponentProps } from 'react'; import { createContext, memo, useContext, useEffect, useState } from 'react'; diff --git a/bandit-runner-app/src/components/ui/shadcn-io/ai/response.tsx b/bandit-runner-app/src/components/ui/shadcn-io/ai/response.tsx index 15a53bc..ed3be86 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/ai/response.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/ai/response.tsx @@ -1,6 +1,6 @@ 'use client'; -import { cn } from '@repo/shadcn-ui/lib/utils'; +import { cn } from '@/lib/utils'; import type { ComponentProps, HTMLAttributes } from 'react'; import { isValidElement, memo } from 'react'; import ReactMarkdown, { type Options } from 'react-markdown'; diff --git a/bandit-runner-app/src/components/ui/shadcn-io/ai/tool.tsx b/bandit-runner-app/src/components/ui/shadcn-io/ai/tool.tsx index 2f83d6a..220d2df 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/ai/tool.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/ai/tool.tsx @@ -1,12 +1,12 @@ 'use client'; -import { Badge } from '@repo/shadcn-ui/components/ui/badge'; +import { Badge } from '@/components/ui/shadcn-io/badge'; import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from '@repo/shadcn-ui/components/ui/collapsible'; -import { cn } from '@repo/shadcn-ui/lib/utils'; +} from '@/components/ui/shadcn-io/collapsible'; +import { cn } from '@/lib/utils'; import type { ToolUIPart } from 'ai'; import { CheckCircleIcon, diff --git a/bandit-runner-app/src/components/ui/alert-dialog.tsx b/bandit-runner-app/src/components/ui/shadcn-io/alert-dialog.tsx similarity index 98% rename from bandit-runner-app/src/components/ui/alert-dialog.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/alert-dialog.tsx index 0863e40..7185ba8 100644 --- a/bandit-runner-app/src/components/ui/alert-dialog.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/alert-dialog.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" +import { buttonVariants } from "@/components/ui/shadcn-io/button" function AlertDialog({ ...props diff --git a/bandit-runner-app/src/components/ui/shadcn-io/avatar.tsx b/bandit-runner-app/src/components/ui/shadcn-io/avatar.tsx new file mode 100644 index 0000000..71e428b --- /dev/null +++ b/bandit-runner-app/src/components/ui/shadcn-io/avatar.tsx @@ -0,0 +1,53 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +function Avatar({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/bandit-runner-app/src/components/ui/badge.tsx b/bandit-runner-app/src/components/ui/shadcn-io/badge.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/badge.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/badge.tsx diff --git a/bandit-runner-app/src/components/ui/button.tsx b/bandit-runner-app/src/components/ui/shadcn-io/button.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/button.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/button.tsx diff --git a/bandit-runner-app/src/components/ui/card.tsx b/bandit-runner-app/src/components/ui/shadcn-io/card.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/card.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/card.tsx diff --git a/bandit-runner-app/src/components/ui/shadcn-io/code-block/index.tsx b/bandit-runner-app/src/components/ui/shadcn-io/code-block/index.tsx index e43e9c2..686563a 100644 --- a/bandit-runner-app/src/components/ui/shadcn-io/code-block/index.tsx +++ b/bandit-runner-app/src/components/ui/shadcn-io/code-block/index.tsx @@ -86,14 +86,14 @@ import { useEffect, useState, } from 'react'; -import { Button } from '@/components/ui/button'; +import { Button } from '@/components/ui/shadcn-io/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from '@/components/ui/select'; +} from '@/components/ui/shadcn-io/select'; import { cn } from '@/lib/utils'; export type BundledLanguage = string; diff --git a/bandit-runner-app/src/components/ui/shadcn-io/collapsible.tsx b/bandit-runner-app/src/components/ui/shadcn-io/collapsible.tsx new file mode 100644 index 0000000..ae9fad0 --- /dev/null +++ b/bandit-runner-app/src/components/ui/shadcn-io/collapsible.tsx @@ -0,0 +1,33 @@ +"use client" + +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +function Collapsible({ + ...props +}: React.ComponentProps) { + return +} + +function CollapsibleTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function CollapsibleContent({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/bandit-runner-app/src/components/ui/dialog.tsx b/bandit-runner-app/src/components/ui/shadcn-io/dialog.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/dialog.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/dialog.tsx diff --git a/bandit-runner-app/src/components/ui/input.tsx b/bandit-runner-app/src/components/ui/shadcn-io/input.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/input.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/input.tsx diff --git a/bandit-runner-app/src/components/ui/label.tsx b/bandit-runner-app/src/components/ui/shadcn-io/label.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/label.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/label.tsx diff --git a/bandit-runner-app/src/components/ui/scroll-area.tsx b/bandit-runner-app/src/components/ui/shadcn-io/scroll-area.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/scroll-area.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/scroll-area.tsx diff --git a/bandit-runner-app/src/components/ui/select.tsx b/bandit-runner-app/src/components/ui/shadcn-io/select.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/select.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/select.tsx diff --git a/bandit-runner-app/src/components/ui/separator.tsx b/bandit-runner-app/src/components/ui/shadcn-io/separator.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/separator.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/separator.tsx diff --git a/bandit-runner-app/src/components/ui/sonner.tsx b/bandit-runner-app/src/components/ui/shadcn-io/sonner.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/sonner.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/sonner.tsx diff --git a/bandit-runner-app/src/components/ui/switch.tsx b/bandit-runner-app/src/components/ui/shadcn-io/switch.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/switch.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/switch.tsx diff --git a/bandit-runner-app/src/components/ui/table.tsx b/bandit-runner-app/src/components/ui/shadcn-io/table.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/table.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/table.tsx diff --git a/bandit-runner-app/src/components/ui/tabs.tsx b/bandit-runner-app/src/components/ui/shadcn-io/tabs.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/tabs.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/tabs.tsx diff --git a/bandit-runner-app/src/components/ui/textarea.tsx b/bandit-runner-app/src/components/ui/shadcn-io/textarea.tsx similarity index 100% rename from bandit-runner-app/src/components/ui/textarea.tsx rename to bandit-runner-app/src/components/ui/shadcn-io/textarea.tsx