diff --git a/dashboard/src/app/workspaces/page.tsx b/dashboard/src/app/workspaces/page.tsx index 713257f..43a4a54 100644 --- a/dashboard/src/app/workspaces/page.tsx +++ b/dashboard/src/app/workspaces/page.tsx @@ -38,6 +38,9 @@ import { Bookmark, FileText, Sparkles, + Eye, + EyeOff, + Lock, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useToast } from '@/components/toast'; @@ -74,7 +77,7 @@ export default function WorkspacesPage() { const [showBuildLogs, setShowBuildLogs] = useState(false); // Workspace settings state - const [envRows, setEnvRows] = useState<{ id: string; key: string; value: string }[]>([]); + const [envRows, setEnvRows] = useState<{ id: string; key: string; value: string; secret: boolean; visible: boolean }[]>([]); const [initScript, setInitScript] = useState(''); const [savingWorkspace, setSavingWorkspace] = useState(false); const [savingTemplate, setSavingTemplate] = useState(false); @@ -115,12 +118,27 @@ export default function WorkspacesPage() { } }; + // Patterns that indicate a sensitive value + const isSensitiveKey = (key: string) => { + const upperKey = key.toUpperCase(); + const sensitivePatterns = [ + 'KEY', 'TOKEN', 'SECRET', 'PASSWORD', 'PASS', 'CREDENTIAL', 'AUTH', + 'PRIVATE', 'API_KEY', 'ACCESS_TOKEN', 'B64', 'BASE64', 'ENCRYPTED', + ]; + return sensitivePatterns.some(pattern => upperKey.includes(pattern)); + }; + const toEnvRows = (env: Record) => - Object.entries(env).map(([key, value]) => ({ - id: `${key}-${Math.random().toString(36).slice(2, 8)}`, - key, - value, - })); + Object.entries(env).map(([key, value]) => { + const secret = isSensitiveKey(key); + return { + id: `${key}-${Math.random().toString(36).slice(2, 8)}`, + key, + value, + secret, + visible: !secret, // Hidden by default if secret + }; + }); const envRowsToMap = (rows: { key: string; value: string }[]) => { const env: Record = {}; @@ -833,7 +851,7 @@ export default function WorkspacesPage() { onClick={() => setEnvRows((rows) => [ ...rows, - { id: Math.random().toString(36).slice(2), key: '', value: '' }, + { id: Math.random().toString(36).slice(2), key: '', value: '', secret: false, visible: true }, ]) } className="text-xs text-indigo-400 hover:text-indigo-300 font-medium" @@ -848,7 +866,7 @@ export default function WorkspacesPage() {

No environment variables

+ )} + + {row.secret && ( + + + + )}