package filemanager import ( "context" "errors" "io" "time" ) const ( SystemRootFolderName = "__system_root_files__" ) var ( ErrDuplicateName = errors.New("duplicate name in target folder") ErrInvalidMove = errors.New("invalid folder move") ErrFolderNotFound = errors.New("folder not found") ErrFileNotFound = errors.New("file not found") ErrFileAlreadyFinalized = errors.New("file already finalized") ErrFileNotEligibleForFinalize = errors.New("file is not eligible for finalize") ErrInvalidFileStatusTransition = errors.New("invalid file status transition") ErrFileStatusConflict = errors.New("file status conflict") ErrStorageUnavailable = errors.New("storage unavailable") ErrFolderNotEmpty = errors.New("folder is not empty") ErrFolderNotInTrash = errors.New("folder is not in trash") ErrFileNotInTrash = errors.New("file is not in trash") ErrInvalidName = errors.New("invalid name") ErrReservedName = errors.New("reserved name") ErrFileTooLarge = errors.New("file too large") ErrFileMimeTypeNotAllowed = errors.New("file mime type is not allowed") ErrFileExtensionNotAllowed = errors.New("file extension is not allowed") ErrEmptyFileNotAllowed = errors.New("empty file is not allowed") ErrFileNameTooLong = errors.New("file name exceeds maximum length") ErrFileProcessingQueueDisabled = errors.New("file processing queue is not configured") ErrUploadIntentRepositoryDisabled = errors.New("file upload intent repository is not configured") ErrUploadIntentNotFound = errors.New("upload intent not found") ErrUploadIntentExpired = errors.New("upload intent is expired") ErrUploadIntentAlreadyComplete = errors.New("upload intent already completed") ErrUploadIntentStatusConflict = errors.New("upload intent status conflict") ErrUploadObjectNotFound = errors.New("uploaded object not found in storage") ErrUploadObjectMismatch = errors.New("uploaded object does not match upload intent") ErrAttachmentRepositoryDisabled = errors.New("attachment repository is not configured") ErrAttachmentNotFound = errors.New("attachment not found") ErrAttachmentAlreadyExists = errors.New("attachment already exists for this reference") ErrAttachmentRefRequired = errors.New("attachment ref_type and ref_id are required") ErrFileNotReadyForAttachment = errors.New("file is not ready for attachment") ) type FileUploadPolicy struct { MaxFileSizeBytes int64 AllowedMimeTypes []string AllowedExtensions []string AllowEmptyFile bool MaxFilenameLength int } type FileProcessingJob struct { JobID string FileUUID string Bucket string ObjectKey string UploadedBy string MimeType string SizeBytes int64 TraceID string RequestID string } type FileProcessingQueue interface { Enqueue(ctx context.Context, job FileProcessingJob) error } type CreateFolderParams struct { Name string ParentID []byte ActorID []byte } type MoveFolderParams struct { Name *string ParentID []byte ParentProvided bool ActorID []byte } type UploadFileParams struct { Name string ContentType string SizeBytes int64 Body io.Reader ActorID []byte IsTemplate bool } type RequestFileUploadIntentParams struct { Name string ContentType string SizeBytes int64 ActorID []byte } type FileUploadIntentGrant struct { UploadIntentID []byte Bucket string ObjectKey string Name string MimeType string SizeBytes int64 Method string UploadURL string Headers map[string]string ExpiresAt time.Time } type CompleteFileUploadIntentParams struct { UploadIntentID []byte ActorID []byte } type CancelFileUploadIntentParams struct { UploadIntentID []byte ActorID []byte } type CreateFileFromUploadParams struct { UploadFileID []byte FolderID []byte FolderProvided bool Name *string ActorID []byte IsTemplate bool } type CreateFileFromUploadIntentParams struct { UploadIntentID []byte FolderID []byte FolderProvided bool Name string ActorID []byte IsTemplate bool } type BulkFileNodeResult struct { Index int File *File Err error } type MoveFileParams struct { Name *string FolderID []byte FolderProvided bool ActorID []byte } type CreateAttachmentParams struct { FileID []byte RefType string RefID string Category *string SortOrder int IsPrimary bool ActorID []byte } type ListAttachmentsParams struct { RefType string RefID string Category *string Sort string Limit int Offset int } type FileCleanupStats struct { Scanned int Deleted int Skipped int Failed int DryRun bool } // LifecycleManager is an optional extension implemented by concrete services // to expose file lifecycle transitions without widening the base Service // interface used by existing handlers/tests. type LifecycleManager interface { MarkFileActive(ctx context.Context, fileID []byte, actorID []byte) error ReconcileFileLifecycle(ctx context.Context, fileID []byte, actorID []byte) error CleanupOrphanPendingFiles(ctx context.Context, now time.Time, gracePeriod time.Duration, limit int, dryRun bool) (FileCleanupStats, error) } type Service interface { SetObjectStorage(storage ObjectStorage) SetUploadPolicy(policy FileUploadPolicy) SetFileProcessingQueue(fileQueue FileProcessingQueue) SetFileUploadIntentRepository(repo FileUploadIntentRepository) RequestFileUploadIntent(ctx context.Context, params RequestFileUploadIntentParams) (*FileUploadIntentGrant, error) CompleteFileUploadIntent(ctx context.Context, params CompleteFileUploadIntentParams) (*File, error) CancelFileUploadIntent(ctx context.Context, params CancelFileUploadIntentParams) error CreateFileNodeFromUploadIntent(ctx context.Context, params CreateFileFromUploadIntentParams) (*File, error) GetOrCreateSystemRootFolder(ctx context.Context) (*Folder, error) CreateFolderNode(ctx context.Context, params CreateFolderParams) (*Folder, error) MoveFolderNode(ctx context.Context, id []byte, params MoveFolderParams) (*Folder, error) UploadFileNode(ctx context.Context, params UploadFileParams) (*File, error) CreateFileNodeFromUpload(ctx context.Context, params CreateFileFromUploadParams) (*File, error) UploadFileNodesBulk(ctx context.Context, params []UploadFileParams) []BulkFileNodeResult CreateFileNodesFromUploadBulk(ctx context.Context, params []CreateFileFromUploadParams) []BulkFileNodeResult MoveFileNode(ctx context.Context, id []byte, params MoveFileParams) (*File, error) PurgeFolderNode(ctx context.Context, id []byte) error PurgeFileNode(ctx context.Context, id []byte) error ListNodesByParent(ctx context.Context, parentID []byte) ([]Folder, []File, error) SearchNodes(ctx context.Context, query string) ([]Folder, []File, error) ListTrashNodes(ctx context.Context) ([]Folder, []File, error) CreateFolder(ctx context.Context, row *Folder) error UpdateFolder(ctx context.Context, row *Folder) error DeleteFolder(ctx context.Context, id []byte, deletedBy []byte, purgeAt *time.Time) error RestoreFolder(ctx context.Context, id []byte, targetParentID []byte, targetProvided bool, restoredBy []byte) error PurgeFolder(ctx context.Context, id []byte) error GetFolderByID(ctx context.Context, id []byte) (*Folder, error) GetFolderByIDAny(ctx context.Context, id []byte) (*Folder, error) GetFolderByParentAndName(ctx context.Context, parentID []byte, nameNormalized string) (*Folder, error) ListFoldersByParent(ctx context.Context, parentID []byte, sort string, limit, offset int) ([]Folder, int64, error) ListTrashFoldersByParent(ctx context.Context, parentID []byte, sort string, limit, offset int) ([]Folder, int64, error) CreateFile(ctx context.Context, row *File) error UpdateFile(ctx context.Context, row *File) error DeleteFile(ctx context.Context, id []byte, deletedBy []byte, purgeAt *time.Time) error RestoreFile(ctx context.Context, id []byte, targetFolderID []byte, targetProvided bool, restoredBy []byte) error PurgeFile(ctx context.Context, id []byte) error GetFileByID(ctx context.Context, id []byte) (*File, error) GetFileByIDAny(ctx context.Context, id []byte) (*File, error) GetFileByObjectKey(ctx context.Context, objectKey string) (*File, error) GetFileByFolderAndName(ctx context.Context, folderID []byte, nameNormalized string) (*File, error) ListFilesByFolder(ctx context.Context, folderID []byte, sort string, limit, offset int) ([]File, int64, error) ListTrashFilesByFolder(ctx context.Context, folderID []byte, sort string, limit, offset int) ([]File, int64, error) CreateAttachment(ctx context.Context, params CreateAttachmentParams) (*Attachment, error) GetAttachmentByID(ctx context.Context, id []byte) (*Attachment, error) ListAttachmentsByReference(ctx context.Context, params ListAttachmentsParams) ([]Attachment, int64, error) DeleteAttachment(ctx context.Context, id []byte) error ListEditedWBFilesByTakeoverID(ctx context.Context, takeoverID []byte) ([]File, error) }