From a1a8193eb133f14122c169a523b3a1d6a22cde4d Mon Sep 17 00:00:00 2001 From: cooper Date: Wed, 23 Sep 2026 04:29:31 -0700 Subject: [PATCH] chore(studio): delete the databases and secrets pages /studio/databases rendered only mock data, and /studio/secrets duplicated the Variables page while showing demo secrets whenever a read failed. Remove both routes and panels, the /api/provision-db and /api/seed-snapshots routes with their seed data, and the GitHub tRPC router, whose only caller was the databases page (the provision-db workflow it dispatched was deleted in 8b009577). Point the overview Secrets tile at /studio/variables and drop the commented-out quick actions that linked to the removed pages. Refs: stackpanel-thq.1 --- .../components/studio/dashboard-header.tsx | 4 - .../components/studio/dashboard-sidebar.tsx | 3 - .../components/studio/overview/stats-grid.tsx | 2 +- .../studio/panels/databases-panel.tsx | 68 --- .../studio/panels/databases/components.tsx | 430 ----------------- .../studio/panels/databases/constants.ts | 59 --- .../studio/panels/databases/index.ts | 8 - .../studio/panels/databases/types.ts | 57 --- .../studio/panels/databases/use-databases.ts | 117 ----- .../studio/panels/overview-panel.tsx | 51 -- .../studio/panels/secrets-panel.tsx | 398 ---------------- .../studio/panels/secrets/constants.ts | 68 --- .../components/studio/panels/secrets/index.ts | 7 - .../components/studio/panels/secrets/types.ts | 24 - .../studio/panels/secrets/use-secrets.ts | 164 ------- apps/web/src/data/seed-snapshots.json | 11 - apps/web/src/routeTree.gen.ts | 84 ---- apps/web/src/routes/api/provision-db.ts | 218 --------- apps/web/src/routes/api/seed-snapshots.ts | 20 - apps/web/src/routes/studio/databases.tsx | 10 - apps/web/src/routes/studio/secrets.tsx | 10 - packages/api/src/routers/github.ts | 437 ------------------ packages/api/src/routers/index.ts | 2 - 23 files changed, 1 insertion(+), 2251 deletions(-) delete mode 100644 apps/web/src/components/studio/panels/databases-panel.tsx delete mode 100644 apps/web/src/components/studio/panels/databases/components.tsx delete mode 100644 apps/web/src/components/studio/panels/databases/constants.ts delete mode 100644 apps/web/src/components/studio/panels/databases/index.ts delete mode 100644 apps/web/src/components/studio/panels/databases/types.ts delete mode 100644 apps/web/src/components/studio/panels/databases/use-databases.ts delete mode 100644 apps/web/src/components/studio/panels/secrets-panel.tsx delete mode 100644 apps/web/src/components/studio/panels/secrets/constants.ts delete mode 100644 apps/web/src/components/studio/panels/secrets/index.ts delete mode 100644 apps/web/src/components/studio/panels/secrets/types.ts delete mode 100644 apps/web/src/components/studio/panels/secrets/use-secrets.ts delete mode 100644 apps/web/src/data/seed-snapshots.json delete mode 100644 apps/web/src/routes/api/provision-db.ts delete mode 100644 apps/web/src/routes/api/seed-snapshots.ts delete mode 100644 apps/web/src/routes/studio/databases.tsx delete mode 100644 apps/web/src/routes/studio/secrets.tsx delete mode 100644 packages/api/src/routers/github.ts diff --git a/apps/web/src/components/studio/dashboard-header.tsx b/apps/web/src/components/studio/dashboard-header.tsx index 21e15fc5..60f2f84e 100644 --- a/apps/web/src/components/studio/dashboard-header.tsx +++ b/apps/web/src/components/studio/dashboard-header.tsx @@ -22,8 +22,6 @@ const panelTitles: Record = { dashboard: "Dashboard", setup: "Setup", services: "Services", - databases: "Databases", - secrets: "Secrets", devshells: "Dev Shells", packages: "Packages", team: "Team", @@ -58,8 +56,6 @@ const pathToPanelMap: Record = { "/studio/configuration": "configuration", "/studio/local-config": "local-config", "/studio/services": "services", - "/studio/databases": "databases", - "/studio/secrets": "secrets", "/studio/devshells": "devshells", "/studio/packages": "packages", "/studio/team": "team", diff --git a/apps/web/src/components/studio/dashboard-sidebar.tsx b/apps/web/src/components/studio/dashboard-sidebar.tsx index 1fba3349..da02cae4 100644 --- a/apps/web/src/components/studio/dashboard-sidebar.tsx +++ b/apps/web/src/components/studio/dashboard-sidebar.tsx @@ -78,13 +78,11 @@ export type PanelType = | "setup" | "apps" | "packages" - | "secrets" | "tasks" | "processes" | "variables" | "configuration" | "local-config" - | "databases" | "devshells" | "team" | "network" @@ -140,7 +138,6 @@ const otherNavItems: NavItem[] = [ ]; const coceptsNavItems: NavItem[] = [ - // { id: "databases", label: "Databases", icon: Database }, { id: "tasks", label: "Tasks", icon: Play }, { id: "services", label: "Services", icon: Server }, { id: "extensions", label: "Extensions", icon: Puzzle }, diff --git a/apps/web/src/components/studio/overview/stats-grid.tsx b/apps/web/src/components/studio/overview/stats-grid.tsx index 833dfc2e..a1470833 100644 --- a/apps/web/src/components/studio/overview/stats-grid.tsx +++ b/apps/web/src/components/studio/overview/stats-grid.tsx @@ -94,7 +94,7 @@ export function StatsGrid() { value: secretCount, subtitle: "Across all environments", icon: KeyRound, - path: "/studio/secrets", + path: "/studio/variables", loading: secretsLoading, }, { diff --git a/apps/web/src/components/studio/panels/databases-panel.tsx b/apps/web/src/components/studio/panels/databases-panel.tsx deleted file mode 100644 index 37b72819..00000000 --- a/apps/web/src/components/studio/panels/databases-panel.tsx +++ /dev/null @@ -1,68 +0,0 @@ -"use client"; - -import { DatabaseCard, CreateDatabaseDialog, useDatabases, MOCK_DATABASES } from "./databases"; - -export function DatabasesPanel() { - const { - dialogOpen, - setDialogOpen, - dbName, - setDbName, - seedSnapshot, - setSeedSnapshot, - runMigrations, - setRunMigrations, - isPaired, - snapshots, - snapshotsLoading, - isProvisioning, - provisioningComplete, - provisioningSuccess, - provisioningError, - workflowRunUrl, - workflowStatus, - handleProvision, - handleDialogClose, - handleRetry: _handleRetry, - } = useDatabases(); - - return ( -
-
-
-

Databases

-

- Manage your database instances and connections -

-
- -
- -
- {MOCK_DATABASES.map((db) => ( - - ))} -
-
- ); -} diff --git a/apps/web/src/components/studio/panels/databases/components.tsx b/apps/web/src/components/studio/panels/databases/components.tsx deleted file mode 100644 index f83c7e5b..00000000 --- a/apps/web/src/components/studio/panels/databases/components.tsx +++ /dev/null @@ -1,430 +0,0 @@ -/** - * Reusable components for the Databases Panel - */ - -import { Badge } from "@ui/badge"; -import { Button } from "@ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@ui/card"; -import { Checkbox } from "@ui/checkbox"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@ui/dialog"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@ui/dropdown-menu"; -import { Input } from "@ui/input"; -import { Label } from "@ui/label"; -import { Progress } from "@ui/progress"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@ui/select"; -import { - AlertCircle, - CheckCircle2, - Clock, - Copy, - Database, - ExternalLink, - HardDrive, - Loader2, - MoreVertical, - Plus, - RefreshCw, - Shield, -} from "lucide-react"; -import type { - DatabaseCardProps, - CreateDatabaseDialogProps, - ProvisioningStatusProps, -} from "./types"; - -// ============================================================================= -// Database Card Component -// ============================================================================= - -export function DatabaseCard({ database }: DatabaseCardProps) { - return ( - - -
-
-
- -
-
- - {database.name} - -

- {database.type} {database.version} -

-
-
-
- - {database.status} - - - - - - - - - Open Console - - View metrics - Backup now - Edit config - - Delete - - - -
-
-
- -
-
- - {database.host} - - -
-
- -
-
- - - Storage - - - {database.storage.used} GB / {database.storage.total} GB - -
- -
- -
-
- - Backup: {database.lastBackup} -
-
- - Connections: {database.connections} -
-
-
-
- ); -} - -// ============================================================================= -// Provisioning Status Component -// ============================================================================= - -export function ProvisioningStatus({ - isProvisioning, - provisioningComplete, - provisioningSuccess, - dbName, - workflowRunUrl, - onClose, - onRetry, - workflowStatus, -}: ProvisioningStatusProps) { - if (isProvisioning) { - return ( -
-
- -
-

- Provisioning database... -

-

- {workflowStatus || "Starting workflow"} -

-
-
- {workflowRunUrl && ( - - View in GitHub Actions - - - )} -
- ); - } - - if (provisioningComplete) { - if (provisioningSuccess) { - return ( -
-
- -
-
-

Database Created!

-

- Your database {dbName} is ready to use. -

-
- {workflowRunUrl && ( - - View workflow details - - - )} - -
- ); - } - - return ( -
-
- -
-
-

Provisioning Failed

-

- Check the workflow logs for details. -

-
- {workflowRunUrl && ( - - View workflow logs - - - )} -
- - -
-
- ); - } - - return null; -} - -// ============================================================================= -// Create Database Dialog -// ============================================================================= - -export function CreateDatabaseDialog({ - open, - onOpenChange, - dbName, - onDbNameChange, - seedSnapshot, - onSeedSnapshotChange, - runMigrations, - onRunMigrationsChange, - onProvision, - onClose, - isProvisioning, - provisioningComplete, - provisioningSuccess, - provisioningError, - workflowRunUrl, - workflowStatus, - isPaired, - snapshots, -}: CreateDatabaseDialogProps) { - return ( - !open && onClose()} - open={open} - > - - - - - - Create New Database - - Provision a new PostgreSQL database on the internal server. - - - - {!provisioningComplete ? ( - <> -
-
- - onDbNameChange(e.target.value)} - placeholder="my_database" - value={dbName} - /> -

- Lowercase letters, numbers, and underscores only -

-
- -
- - -
- -
- - onRunMigrationsChange(checked === true) - } - /> - -
- - {!isPaired && ( -
-

- - Connect to the local agent to save credentials to your - project. -

-
- )} - - {provisioningError && ( -
-

- {provisioningError} -

-
- )} - - {}} - workflowStatus={workflowStatus} - /> -
- - - - - - - ) : ( - {}} - workflowStatus={workflowStatus} - /> - )} -
-
- ); -} diff --git a/apps/web/src/components/studio/panels/databases/constants.ts b/apps/web/src/components/studio/panels/databases/constants.ts deleted file mode 100644 index 92f94365..00000000 --- a/apps/web/src/components/studio/panels/databases/constants.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Constants and mock data for Databases Panel - */ - -import type { Database } from "./types"; - -export const MOCK_DATABASES: Database[] = [ - { - name: "main-postgres", - type: "PostgreSQL", - version: "15.2", - status: "online", - connections: "23/100", - storage: { used: 12.4, total: 50 }, - host: "main-postgres.internal.acme.com", - lastBackup: "2 hours ago", - ssl: true, - }, - { - name: "auth-postgres", - type: "PostgreSQL", - version: "15.2", - status: "online", - connections: "8/50", - storage: { used: 2.1, total: 20 }, - host: "auth-postgres.internal.acme.com", - lastBackup: "1 hour ago", - ssl: true, - }, - { - name: "cache-redis", - type: "Redis", - version: "7.0", - status: "online", - connections: "156/1000", - storage: { used: 0.8, total: 4 }, - host: "cache-redis.internal.acme.com", - lastBackup: "N/A", - ssl: true, - }, - { - name: "analytics-clickhouse", - type: "ClickHouse", - version: "23.3", - status: "online", - connections: "12/50", - storage: { used: 45.2, total: 200 }, - host: "analytics-clickhouse.internal.acme.com", - lastBackup: "6 hours ago", - ssl: true, - }, -]; - -/** - * Normalize database name to valid format - */ -export function normalizeDatabaseName(name: string): string { - return name.toLowerCase().replace(/[^a-z0-9_]/g, "_"); -} diff --git a/apps/web/src/components/studio/panels/databases/index.ts b/apps/web/src/components/studio/panels/databases/index.ts deleted file mode 100644 index 434c18e7..00000000 --- a/apps/web/src/components/studio/panels/databases/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Databases Panel - Barrel Export - */ - -export * from "./types"; -export * from "./constants"; -export * from "./components"; -export * from "./use-databases"; diff --git a/apps/web/src/components/studio/panels/databases/types.ts b/apps/web/src/components/studio/panels/databases/types.ts deleted file mode 100644 index b15ddbb1..00000000 --- a/apps/web/src/components/studio/panels/databases/types.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Type definitions for Databases Panel - */ - -export interface DatabaseStorage { - used: number; - total: number; -} - -export interface Database { - name: string; - type: string; - version: string; - status: "online" | "offline"; - connections: string; - storage: DatabaseStorage; - host: string; - lastBackup: string; - ssl: boolean; -} - -export interface CreateDatabaseDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - dbName: string; - onDbNameChange: (name: string) => void; - seedSnapshot: string; - onSeedSnapshotChange: (snapshot: string) => void; - runMigrations: boolean; - onRunMigrationsChange: (run: boolean) => void; - onProvision: () => void; - onClose: () => void; - isProvisioning: boolean; - provisioningComplete: boolean; - provisioningSuccess: boolean; - provisioningError: string | null; - workflowRunUrl: string | null; - workflowStatus: string | null; - isPaired: boolean; - snapshots: Array<{ key: string; description?: string; isDefault?: boolean }>; - snapshotsLoading: boolean; -} - -export interface DatabaseCardProps { - database: Database; -} - -export interface ProvisioningStatusProps { - isProvisioning: boolean; - provisioningComplete: boolean; - provisioningSuccess: boolean; - dbName: string; - workflowRunUrl: string | null; - onClose: () => void; - onRetry: () => void; - workflowStatus: string | null; -} diff --git a/apps/web/src/components/studio/panels/databases/use-databases.ts b/apps/web/src/components/studio/panels/databases/use-databases.ts deleted file mode 100644 index 43f1855b..00000000 --- a/apps/web/src/components/studio/panels/databases/use-databases.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * State management hook for Databases Panel - */ - -import { useMutation, useQuery } from "@tanstack/react-query"; -import { useState } from "react"; -import { useAgentHealth } from "@/lib/use-agent"; -import { useTRPC } from "@/utils/trpc"; -import { normalizeDatabaseName } from "./constants"; - -export function useDatabases() { - const [dialogOpen, setDialogOpen] = useState(false); - const [dbName, setDbName] = useState(""); - const [seedSnapshot, setSeedSnapshot] = useState("empty"); - const [runMigrations, setRunMigrations] = useState(true); - const [provisioningRunId, setProvisioningRunId] = useState( - null, - ); - - const { isPaired } = useAgentHealth(); - const trpc = useTRPC(); - - // Query for available snapshots - const snapshotsQuery = useQuery(trpc.github.listSnapshots.queryOptions()); - - // Mutation to provision database - const provisionMutation = useMutation( - trpc.github.provisionDatabase.mutationOptions({ - onSuccess: (data) => { - if (data.runId) { - setProvisioningRunId(data.runId); - } - }, - }), - ); - - // Query to poll workflow status - const workflowStatusQuery = useQuery({ - ...trpc.github.getWorkflowRun.queryOptions({ runId: provisioningRunId! }), - enabled: provisioningRunId !== null, - refetchInterval: (query) => { - const data = query.state.data; - if (data?.status === "completed") { - return false; - } - return 3000; // Poll every 3 seconds - }, - }); - - const handleProvision = async () => { - if (!dbName.trim()) return; - - provisionMutation.mutate({ - databaseName: normalizeDatabaseName(dbName), - seedSnapshot: seedSnapshot === "empty" ? undefined : seedSnapshot, - runMigrations, - }); - }; - - const handleDialogClose = () => { - setDialogOpen(false); - setDbName(""); - setSeedSnapshot("empty"); - setRunMigrations(true); - setProvisioningRunId(null); - provisionMutation.reset(); - }; - - const handleRetry = () => { - setProvisioningRunId(null); - provisionMutation.reset(); - }; - - const isProvisioning = - provisionMutation.isPending || - (provisioningRunId !== null && - workflowStatusQuery.data?.status !== "completed"); - - const provisioningComplete = - provisioningRunId !== null && - workflowStatusQuery.data?.status === "completed"; - - const provisioningSuccess = - provisioningComplete && workflowStatusQuery.data?.conclusion === "success"; - - return { - // Dialog state - dialogOpen, - setDialogOpen, - dbName, - setDbName, - seedSnapshot, - setSeedSnapshot, - runMigrations, - setRunMigrations, - - // Agent status - isPaired, - - // Snapshots - snapshots: snapshotsQuery.data?.snapshots ?? [], - snapshotsLoading: snapshotsQuery.isLoading, - - // Provisioning status - isProvisioning, - provisioningComplete, - provisioningSuccess, - provisioningError: provisionMutation.error?.message ?? null, - workflowRunUrl: provisionMutation.data?.runUrl ?? null, - workflowStatus: workflowStatusQuery.data?.status ?? null, - - // Actions - handleProvision, - handleDialogClose, - handleRetry, - }; -} diff --git a/apps/web/src/components/studio/panels/overview-panel.tsx b/apps/web/src/components/studio/panels/overview-panel.tsx index 23c89597..3feee698 100644 --- a/apps/web/src/components/studio/panels/overview-panel.tsx +++ b/apps/web/src/components/studio/panels/overview-panel.tsx @@ -50,57 +50,6 @@ export function OverviewPanel() { {/* Stats Grid - Real data */} - {/* Quick Actions */} - {/*
- - - - Quick Actions - - - -
- - - - - - - - - - - - -
-
-
-
*/} - {/* Health Summary */} diff --git a/apps/web/src/components/studio/panels/secrets-panel.tsx b/apps/web/src/components/studio/panels/secrets-panel.tsx deleted file mode 100644 index 41c32a0b..00000000 --- a/apps/web/src/components/studio/panels/secrets-panel.tsx +++ /dev/null @@ -1,398 +0,0 @@ -"use client"; - -import { Badge } from "@ui/badge"; -import { Button } from "@ui/button"; -import { Card, CardContent } from "@ui/card"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@ui/dialog"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@ui/dropdown-menu"; -import { Input } from "@ui/input"; -import { Label } from "@ui/label"; -import { Tabs, TabsList, TabsTrigger } from "@ui/tabs"; -import { Textarea } from "@ui/textarea"; -import { - AlertCircle, - Clock, - Copy, - Eye, - EyeOff, - KeyRound, - Loader2, - Lock, - MoreVertical, - Plus, - RefreshCw, - Search, - Shield, - Trash2, -} from "lucide-react"; -import { useVariablesBackend } from "@/lib/use-agent"; -import { getTypeColor, useSecrets } from "./secrets"; - -export function SecretsPanel() { - const { data: backendData } = useVariablesBackend(); - const isChamber = backendData?.backend === "chamber"; - - const { - // State - searchQuery, - setSearchQuery, - dialogOpen, - setDialogOpen, - selectedEnvironment, - setSelectedEnvironment, - newSecretKey, - setNewSecretKey, - newSecretValue, - setNewSecretValue, - showSecret, - setShowSecret, - secretValues, - isLoading, - isSaving, - error, - isPaired, - - // Computed - filteredSecrets, - - // Handlers - loadSecrets, - handleAddSecret, - handleDeleteSecret, - } = useSecrets(); - - if (isChamber) { - return ( -
-
-

Secrets

-

- Secrets are managed via AWS Parameter Store (Chamber) -

-
- - - -

- This project uses the Chamber backend for secrets management. - Secrets are stored in AWS Systems Manager Parameter Store and encrypted via KMS. -

-

- Use the Variables & Secrets panel to manage secrets in the{" "} - /dev/,{" "} - /staging/, and{" "} - /prod/ keygroups. -

-
-
-
- ); - } - - return ( -
-
-
-

Secrets

-

- Manage encrypted secrets using age encryption with team public keys -

-
- - - - - - - Add New Secret - - Secrets are encrypted with your team members' public keys using - age. - - -
-
- - - setNewSecretKey(e.target.value.toUpperCase()) - } - placeholder="MY_SECRET_KEY" - value={newSecretKey} - /> -
-
- -