@@ -164,6 +164,7 @@ vi.mock('@/app/api/files/authorization', () => ({
164164
165165import { fileManageBodySchema } from '@/lib/api/contracts/tools/file'
166166import { executeFileManageOperation } from '@/lib/internal/file/operations'
167+ import { FileConflictError } from '@/lib/uploads/contexts/workspace'
167168import { createWorkspaceFileDelegatedPrincipal } from '@/lib/workspace-files/application/delegated-principal'
168169
169170async function POST ( request : Request ) : Promise < Response > {
@@ -676,10 +677,29 @@ describe('file manage operations', () => {
676677 Buffer . from ( 'fresh' ) ,
677678 'report.txt' ,
678679 'text/plain' ,
679- expect . objectContaining ( { exactName : false , folderId : null } )
680+ // Exact, so a path created by a concurrent write conflicts instead of being suffixed.
681+ expect . objectContaining ( { exactName : true , folderId : null } )
680682 )
681683 } )
682684
685+ it ( 'surfaces a conflict when a concurrent write claims the overwrite path' , async ( ) => {
686+ mockResolveWorkspaceFileReference . mockResolvedValue ( null )
687+ mockUploadWorkspaceFile . mockRejectedValue ( new FileConflictError ( 'report.txt' ) )
688+
689+ const response = await POST (
690+ createMockRequest ( 'POST' , {
691+ operation : 'write' ,
692+ workspaceId : 'workspace-1' ,
693+ fileName : 'report.txt' ,
694+ content : 'fresh' ,
695+ overwrite : true ,
696+ } )
697+ )
698+
699+ expect ( response . status ) . toBe ( 409 )
700+ await expect ( response . json ( ) ) . resolves . toMatchObject ( { success : false } )
701+ } )
702+
683703 it ( 'never overwrites a same-named file resolved outside the target folder' , async ( ) => {
684704 mockResolveWorkspaceFileReference . mockResolvedValue ( {
685705 ...workspaceFile ( 'report' ) ,
0 commit comments