diff --git a/internal/http/storage.go b/internal/http/storage.go index 73f1333b..8d59ef70 100644 --- a/internal/http/storage.go +++ b/internal/http/storage.go @@ -65,9 +65,10 @@ func (h *StorageHandler) tenantBaseDir(r *http.Request) string { return config.TenantDataDir(h.baseDir, tid, slug) } -// protectedDirs are top-level directories where deletion is blocked -// (managed separately via the Skills page). -var protectedDirs = []string{"skills", "skills-store"} +// protectedDirs are top-level directories where upload, move, and deletion are blocked. +// These are system-managed: skills (managed via Skills page), media (managed via media handler), +// tenants (tenant isolation root — each tenant's data is scoped internally). +var protectedDirs = []string{"skills", "skills-store", "media", "tenants"} func isProtectedPath(rel string) bool { top := rel diff --git a/internal/tools/workspace_dir.go b/internal/tools/workspace_dir.go index a6fb89db..95246483 100644 --- a/internal/tools/workspace_dir.go +++ b/internal/tools/workspace_dir.go @@ -11,7 +11,7 @@ import ( // Workspace limits shared across workspace interceptor and HTTP upload handlers. const ( - maxFileSizeBytes = 10 * 1024 * 1024 // 10MB + maxFileSizeBytes = 50 * 1024 * 1024 // 50MB maxFilesPerScope = 100 // MaxFileSizeBytes is the exported form of maxFileSizeBytes for HTTP handlers. diff --git a/ui/web/src/components/shared/file-upload-dialog.tsx b/ui/web/src/components/shared/file-upload-dialog.tsx index 05a7d53b..99cd5670 100644 --- a/ui/web/src/components/shared/file-upload-dialog.tsx +++ b/ui/web/src/components/shared/file-upload-dialog.tsx @@ -12,7 +12,7 @@ const BLOCKED_EXTENSIONS = new Set([ ".exe", ".sh", ".bat", ".cmd", ".ps1", ".com", ".msi", ".scr", ]); -const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB — matches backend tools.MaxFileSizeBytes +const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB — matches backend tools.MaxFileSizeBytes type FileStatus = "checking" | "ready" | "uploading" | "success" | "error"; diff --git a/ui/web/src/i18n/locales/en/common.json b/ui/web/src/i18n/locales/en/common.json index ac4ce8de..aaaeb56f 100644 --- a/ui/web/src/i18n/locales/en/common.json +++ b/ui/web/src/i18n/locales/en/common.json @@ -124,9 +124,9 @@ "title": "Upload Files", "dropOrClick": "Drop files here or click to browse", "dropHere": "Drop files here", - "maxSize": "Max 10 MB per file", + "maxSize": "Max 50 MB per file", "blockedType": "File type {{ext}} is not allowed", - "tooLarge": "File exceeds 10 MB limit", + "tooLarge": "File exceeds 50 MB limit", "failed": "Upload failed", "readyCount": "{{ready}} of {{total}} files ready", "successCount": "{{success}} of {{total}} files uploaded", diff --git a/ui/web/src/i18n/locales/vi/common.json b/ui/web/src/i18n/locales/vi/common.json index c2321f12..d75d66c9 100644 --- a/ui/web/src/i18n/locales/vi/common.json +++ b/ui/web/src/i18n/locales/vi/common.json @@ -124,9 +124,9 @@ "title": "Tải tệp lên", "dropOrClick": "Kéo thả tệp hoặc nhấp để chọn", "dropHere": "Thả tệp vào đây", - "maxSize": "Tối đa 10 MB mỗi tệp", + "maxSize": "Tối đa 50 MB mỗi tệp", "blockedType": "Loại tệp {{ext}} không được phép", - "tooLarge": "Tệp vượt quá giới hạn 10 MB", + "tooLarge": "Tệp vượt quá giới hạn 50 MB", "failed": "Tải lên thất bại", "readyCount": "{{ready}} trong {{total}} tệp sẵn sàng", "successCount": "{{success}} trong {{total}} tệp đã tải lên", diff --git a/ui/web/src/i18n/locales/zh/common.json b/ui/web/src/i18n/locales/zh/common.json index efdf956c..ab2b86f2 100644 --- a/ui/web/src/i18n/locales/zh/common.json +++ b/ui/web/src/i18n/locales/zh/common.json @@ -124,9 +124,9 @@ "title": "上传文件", "dropOrClick": "拖放文件或点击浏览", "dropHere": "将文件拖放到这里", - "maxSize": "每个文件最大 10 MB", + "maxSize": "每个文件最大 50 MB", "blockedType": "不允许 {{ext}} 文件类型", - "tooLarge": "文件超过 10 MB 限制", + "tooLarge": "文件超过 50 MB 限制", "failed": "上传失败", "readyCount": "{{total}} 个文件中有 {{ready}} 个就绪", "successCount": "{{total}} 个文件中已上传 {{success}} 个",