@@ -149,6 +149,7 @@ import {
149149} from '@/lib/uploads/contexts/workspace/workspace-file-manager'
150150import type { WorkspaceFileSecretProvenance } from '@/lib/uploads/contexts/workspace/workspace-file-secret-provenance'
151151import { WORKSPACE_FILES_DELEGATION_AUDIENCE } from '@/lib/workspace-files/application/authorization'
152+ import { downloadWorkspaceFileItems } from '@/lib/workspace-files/application/download-workspace-file-items'
152153import { readWorkspaceFileContent } from '@/lib/workspace-files/application/read-workspace-file-content'
153154import {
154155 getWorkspaceFileShares ,
@@ -431,6 +432,59 @@ describe('content reaching Chat is admitted per item', () => {
431432 expect ( read . body ) . toContain ( fixture . files . entries )
432433 } )
433434
435+ it . each ( [ 'uncached' , 'cached' , 'recovered' , 'user-error' , 'subsequent-error' ] as const ) (
436+ 'keeps generated-document refusals per item (%s archive)' ,
437+ async ( kind ) => {
438+ const input = fixture . files . unknown
439+ const read = `await getFileBase64('${ input } ');`
440+ const code =
441+ kind === 'recovered'
442+ ? `try { ${ read } } catch {} pdf.addPage().drawText('safe fallback');`
443+ : kind === 'user-error'
444+ ? `const error = new Error('File cannot be sent to a model because its secret provenance is unavailable'); error.name = 'ContentRefusedError'; throw error;`
445+ : kind === 'subsequent-error'
446+ ? `try { ${ read } } catch {} throw new Error('fixture compiler failure');`
447+ : `${ read } pdf.addPage().drawText('fixture render');`
448+ const document = await uploadWorkspaceFile (
449+ ws ( ) ,
450+ fixture . ids . aliceId ,
451+ Buffer . from ( `const archiveFixture = '${ generateId ( ) } '; ${ code } ` ) ,
452+ `archive-refusal-${ generateId ( ) } .pdf` ,
453+ 'text/x-python-pdf' ,
454+ { notifyWorkspaceChange : false , secretProvenance : { status : 'exact' , entries : [ ] } }
455+ )
456+ if ( kind === 'cached' ) {
457+ const warmed = await downloadWorkspaceFileItems . execute ( {
458+ principal : createSessionPrincipal ( { userId : fixture . ids . aliceId } ) ,
459+ input : { workspaceId : ws ( ) , fileIds : [ document . id ] , folderIds : [ ] } ,
460+ } )
461+ expect ( warmed . renderedDocuments . get ( document . id ) ?. subarray ( 0 , 4 ) . toString ( ) ) . toBe ( '%PDF' )
462+ }
463+ const route = `/api/v2/files/bulk-download?workspaceId=${ ws ( ) } &fileIds=`
464+ const mixed = await cli ( 'GET' , `${ route } ${ fixture . files . clean } ,${ document . id } ` )
465+ if ( kind === 'user-error' || kind === 'subsequent-error' ) {
466+ expect ( mixed . status ) . toBe ( 500 )
467+ expect ( mixed . body ) . toContain ( 'INTERNAL_ERROR' )
468+ return
469+ }
470+ expect ( mixed . status , mixed . body ) . toBe ( 200 )
471+ expect ( mixed . body ) . toContain ( CANARY . clean )
472+ expect ( mixed . body ) . not . toContain ( CANARY . unknown )
473+ expect ( mixed . registry . isPermanentlyIncomplete ( ) ) . toBe ( false )
474+ if ( kind === 'recovered' ) {
475+ expect ( mixed . body ) . toContain ( '%PDF' )
476+ expect ( mixed . body ) . not . toContain ( 'sim-download-report.json' )
477+ } else {
478+ expect ( mixed . body ) . not . toContain ( '%PDF' )
479+ expect ( mixed . body ) . toContain ( 'sim-download-report.json' )
480+ expect ( mixed . body ) . toContain ( document . id )
481+ const alone = await cli ( 'GET' , `${ route } ${ document . id } ` )
482+ expect ( alone . status , alone . body ) . toBe ( 403 )
483+ expect ( alone . body ) . not . toContain ( CANARY . unknown )
484+ }
485+ }
486+ )
487+
434488 it ( 'answers files search with locations and withheld unreadable previews (#5, misroute)' , async ( ) => {
435489 const read = await cli (
436490 'GET' ,
0 commit comments