diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 97503ba21..c3cbf3e89 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -14,7 +14,7 @@ import "./styles/cookieconsent.css"; import "./index.css"; import { RightRailProvider } from "./contexts/RightRailContext"; -// Import file ID safety validators (development only) +// Import file ID debugging helpers (development only) import "./utils/fileIdSafety"; // Loading component for i18next suspense diff --git a/frontend/src/contexts/FileContext.tsx b/frontend/src/contexts/FileContext.tsx index 3efaa01a4..a79303c33 100644 --- a/frontend/src/contexts/FileContext.tsx +++ b/frontend/src/contexts/FileContext.tsx @@ -124,7 +124,7 @@ function FileContextInner({ // Helper functions for pinned files const consumeFilesWrapper = useCallback(async (inputFileIds: FileId[], outputFiles: File[]): Promise => { - return consumeFiles(inputFileIds, outputFiles, stateRef, filesRef, dispatch, indexedDB); + return consumeFiles(inputFileIds, outputFiles, filesRef, dispatch, indexedDB); }, [indexedDB]); const undoConsumeFilesWrapper = useCallback(async (inputFiles: File[], inputWorkbenchFiles: WorkbenchFile[], outputFileIds: FileId[]): Promise => { diff --git a/frontend/src/types/fileIdSafety.d.ts b/frontend/src/types/fileIdSafety.d.ts index 9316af45a..08888d4c0 100644 --- a/frontend/src/types/fileIdSafety.d.ts +++ b/frontend/src/types/fileIdSafety.d.ts @@ -24,10 +24,9 @@ declare global { type RequireStirlingFile = T extends File ? StirlingFile : T; } - // Extend Window interface to add runtime validation helpers + // Extend Window interface for debugging interface Window { __FILE_ID_DEBUG?: boolean; - __validateFileId?: (id: string, context: string) => void; } } diff --git a/frontend/src/utils/fileIdSafety.ts b/frontend/src/utils/fileIdSafety.ts index 6837786ed..3fda8a4a5 100644 --- a/frontend/src/utils/fileIdSafety.ts +++ b/frontend/src/utils/fileIdSafety.ts @@ -11,69 +11,4 @@ export function isValidFileId(id: string): id is FileId { return uuidRegex.test(id); } -// Detect potentially dangerous file.name usage as ID -export function isDangerousFileNameAsId(fileName: string, context: string = ''): boolean { - // Check if it's definitely a UUID (safe) - if (isValidFileId(fileName)) { - return false; - } - - // Check if it's a quickKey (safe) - format: name|size|lastModified - if (/^.+\|\d+\|\d+$/.test(fileName)) { - return false; // quickKeys are legitimate, not dangerous - } - - // Common patterns that suggest file.name is being used as ID - const dangerousPatterns = [ - /^[^-]+-page-\d+$/, // pattern: filename-page-123 - /\.(pdf|jpg|png|doc|docx)$/i, // ends with file extension - /\s/, // contains whitespace (filenames often have spaces) - /[()[\]{}]/, // contains brackets/parentheses common in filenames - /['"]/, // contains quotes - /[^a-zA-Z0-9\-._]/ // contains special characters not in UUIDs - ]; - - // Check dangerous patterns - const isDangerous = dangerousPatterns.some(pattern => pattern.test(fileName)); - - if (isDangerous && context) { - console.warn(`⚠️ Potentially dangerous file.name usage detected in ${context}: "${fileName}"`); - } - - return isDangerous; -} -// Runtime validation for FileId usage in development -export function validateFileId(id: string, context: string): void { - if (process.env.NODE_ENV === 'development') { - // Check if it looks like a dangerous file.name usage - if (isDangerousFileNameAsId(id, context)) { - console.error(`💀 DANGEROUS: file.name used as FileId in ${context}! This will cause ID collisions.`); - console.trace('Stack trace:'); - } - } -} - -// Runtime validation for File vs FileWithId usage -export function validateFileWithId(file: File, context: string): void { - // Check if file has embedded fileId - if (!('fileId' in file)) { - console.warn(`⚠️ Regular File object used where FileWithId expected in ${context}: "${file.name}"`); - console.warn('Consider using FileWithId for better type safety'); - } -} - -// Assertion for FileId validation (throws in development) -export function assertValidFileId(id: string, context: string): void { - if (process.env.NODE_ENV === 'development') { - if (isDangerousFileNameAsId(id, context)) { - throw new Error(`ASSERTION FAILED: Dangerous file.name as FileId detected in ${context}: "${id}"`); - } - } -} - -// Global debug helpers (can be enabled in dev tools) -if (typeof window !== 'undefined') { - window.__FILE_ID_DEBUG = process.env.NODE_ENV === 'development'; - window.__validateFileId = validateFileId; -} \ No newline at end of file