import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Modal } from '../components/ui/Modal'; import { useHealth } from '../api/queries/health'; import { useToast } from '../contexts/ToastContext'; import { ApiError } from '../api/client'; import { useStartScan, type ScanMode, type EngineProfile, type StartScanBody, } from '../api/mutations/scans'; interface NewScanModalProps { open: boolean; onClose: () => void; } const MODE_HINTS: Record = { full: 'AST + CFG + taint (default)', ast: 'AST patterns only. Fastest.', cfg: 'CFG structural + taint', taint: 'Taint flows only', }; const PROFILE_HINTS: Record = { fast: 'Basic taint. No abstract-interp / context-sensitive / symex / backwards.', balanced: 'Default. Adds abstract-interp + context-sensitive inlining.', deep: 'Adds symex (cross-file + interproc) and demand-driven backwards taint. About 2 to 3x slower.', }; export function NewScanModal({ open, onClose }: NewScanModalProps) { const { data: health } = useHealth(); const startScan = useStartScan(); const navigate = useNavigate(); const toast = useToast(); const defaultRoot = health?.scan_root || ''; const [scanRoot, setScanRoot] = useState(''); const [mode, setMode] = useState('full'); const [engineProfile, setEngineProfile] = useState('balanced'); const handleStart = async () => { const root = scanRoot.trim(); const body: StartScanBody = {}; if (root && root !== defaultRoot) body.scan_root = root; if (mode !== 'full') body.mode = mode; body.engine_profile = engineProfile; const payload = Object.keys(body).length ? body : undefined; try { await startScan.mutateAsync(payload); toast.success('Scan started', 'Started'); onClose(); navigate('/scans'); } catch (e) { const msg = e instanceof ApiError && e.status === 409 ? 'A scan is already running' : e instanceof Error ? e.message : 'Failed to start scan'; toast.error(msg, 'Could not start scan'); } }; if (!open) return null; return (

Start new scan

setScanRoot(e.target.value)} placeholder="/path/to/project" />
{MODE_HINTS[mode]}
{PROFILE_HINTS[engineProfile]}
); }