@@ -8,6 +8,7 @@ import { mkdtempSync } from 'node:fs'
88import { rm } from 'node:fs/promises'
99import { tmpdir } from 'node:os'
1010import path from 'node:path'
11+ import { createSessionPrincipal } from '@sim/testing/factories/principal.factory'
1112import { featureFlagsMock , featureFlagsMockFns } from '@sim/testing/mocks/feature-flags.mock'
1213import { rateLimiterMock } from '@sim/testing/mocks/rate-limiter.mock'
1314import { generateId } from '@sim/utils/id'
@@ -108,13 +109,22 @@ import { createCopilotChatPrincipal } from '@/lib/mothership/auth/application-de
108109import { createRegistryContentGate } from '@/lib/mothership/content-delivery/registry-gate'
109110import { proxySandboxResourceRequest } from '@/lib/mothership/tools/sandbox-resource-transport'
110111import { chatSandboxSessionKey } from '@/lib/mothership/tools/sandbox-session-key'
112+ import { resolveServableDoc } from '@/lib/mothership/tools/server/files/doc-compile'
113+ import { getShareForResource } from '@/lib/public-shares/share-manager'
111114import {
112115 createOwnedWorkspaceFile ,
116+ getWorkspaceFile ,
117+ updateWorkspaceFileContent as replaceFixtureFileContent ,
113118 uploadWorkspaceFile ,
114119} from '@/lib/uploads/contexts/workspace/workspace-file-manager'
115120import type { WorkspaceFileSecretProvenance } from '@/lib/uploads/contexts/workspace/workspace-file-secret-provenance'
116121import { WORKSPACE_FILES_DELEGATION_AUDIENCE } from '@/lib/workspace-files/application/authorization'
117122import { readWorkspaceFileContent } from '@/lib/workspace-files/application/read-workspace-file-content'
123+ import {
124+ getWorkspaceFileShares ,
125+ updateWorkspaceFileShare ,
126+ } from '@/lib/workspace-files/application/share-workspace-file'
127+ import { storeCompiledDoc } from '@/lib/workspace-files/compiled-document-store'
118128import { indexWorkspaceFileForSearch } from '@/lib/workspace-files/search/indexing'
119129import { projectResolvedSecretModelContent } from '@/executor/utils/resolved-secret-content-projection'
120130import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry'
@@ -176,6 +186,8 @@ describe('content reaching Chat is admitted per item', () => {
176186
177187 beforeAll ( async ( ) => {
178188 fixtureStorage . root = mkdtempSync ( path . join ( tmpdir ( ) , 'sim-content-delivery-' ) )
189+ // Compile the lazy tool graph before request deadlines and per-case provider fixtures exist.
190+ await matchV2Route ( '/api/v2/tools/file_get_content/execute' ) ?. load ( )
179191 fixture = await seedContentFixture ( )
180192 connector = await seedKnowledgeConnector ( fixture )
181193 } , 120_000 )
@@ -578,6 +590,147 @@ describe('content reaching Chat is admitted per item', () => {
578590 expect ( ( await share ( fixture . files . entries ) ) . status ) . toBe ( 403 )
579591 expect ( ( await share ( fixture . files . clean ) ) . status ) . toBe ( 200 )
580592 } )
593+ it . each ( [
594+ 'clean' ,
595+ 'unrecorded' ,
596+ 'secret' ,
597+ 'unknown' ,
598+ 'old-secret' ,
599+ 'malformed' ,
600+ 'invalid' ,
601+ 'mislabeled' ,
602+ 'uploaded' ,
603+ 'legacy' ,
604+ ] as const ) (
605+ 'checks the published document inputs before exposing a share (%s)' ,
606+ async ( kind ) => {
607+ const entries = [
608+ {
609+ name : 'COMPILED_INPUT' ,
610+ encryptedValue : ( await encryptSecret ( CANARY . secret ) ) . encrypted ,
611+ sourceUserId : fixture . ids . aliceId ,
612+ sourceWorkspaceId : ws ( ) ,
613+ } ,
614+ ]
615+ const inputContent = kind === 'clean' ? CANARY . clean : CANARY . secret
616+ const input = await uploadWorkspaceFile (
617+ ws ( ) ,
618+ fixture . ids . aliceId ,
619+ Buffer . from ( inputContent ) ,
620+ `compiled-input-${ generateId ( ) } .txt` ,
621+ 'text/plain' ,
622+ {
623+ notifyWorkspaceChange : false ,
624+ secretProvenance :
625+ kind === 'unknown'
626+ ? { status : 'unknown' }
627+ : kind === 'unrecorded'
628+ ? { status : 'unrecorded' }
629+ : { status : 'exact' , entries : kind === 'clean' ? [ ] : entries } ,
630+ }
631+ )
632+ const record = await getWorkspaceFile ( ws ( ) , input . id , { throwOnError : true } )
633+ if ( ! record ) throw new Error ( 'Missing compiled input fixture' )
634+ const source =
635+ kind === 'uploaded'
636+ ? '%PDF-1.7\nordinary uploaded binary'
637+ : `data = open(input_path("${ input . id } "), "rb").read()`
638+ const document = await uploadWorkspaceFile (
639+ ws ( ) ,
640+ fixture . ids . aliceId ,
641+ Buffer . from ( source ) ,
642+ `compiled-share-${ generateId ( ) } .pdf` ,
643+ kind === 'mislabeled' || kind === 'uploaded' ? 'application/pdf' : 'text/x-python-pdf' ,
644+ { notifyWorkspaceChange : false , secretProvenance : { status : 'exact' , entries : [ ] } }
645+ )
646+ const identity = JSON . stringify ( {
647+ version : 1 ,
648+ inputs : [
649+ {
650+ fileId : input . id ,
651+ key : record . key ,
652+ context : record . storageContext ?? 'workspace' ,
653+ contentVersion : ( record . contentUpdatedAt ?? record . updatedAt ) . toISOString ( ) ,
654+ size : record . size ,
655+ } ,
656+ ] ,
657+ } )
658+ const artifact = Buffer . from ( `%PDF-1.7\n${ inputContent } ` )
659+ await storeCompiledDoc (
660+ ws ( ) ,
661+ source ,
662+ 'pdf' ,
663+ 'application/pdf' ,
664+ artifact ,
665+ kind === 'legacy'
666+ ? undefined
667+ : kind === 'malformed'
668+ ? '{invalid'
669+ : kind === 'invalid'
670+ ? JSON . stringify ( { version : 1 , inputs : [ { } ] } )
671+ : identity
672+ )
673+ const published = await resolveServableDoc ( ws ( ) , Buffer . from ( source ) , document . name )
674+ expect ( published . kind ) . toBe ( kind === 'uploaded' ? 'passthrough' : 'artifact' )
675+ if ( published . kind === 'artifact' ) expect ( published . buffer ) . toEqual ( artifact )
676+ if ( kind === 'old-secret' ) {
677+ await replaceFixtureFileContent (
678+ ws ( ) ,
679+ input . id ,
680+ fixture . ids . aliceId ,
681+ Buffer . from ( 'now clean' ) ,
682+ undefined ,
683+ {
684+ version : { source : 'api' , authorUserId : fixture . ids . aliceId } ,
685+ secretProvenancePolicy : {
686+ mode : 'replace' ,
687+ provenance : { status : 'exact' , entries : [ ] } ,
688+ } ,
689+ }
690+ )
691+ }
692+ const allowed = [ 'clean' , 'unrecorded' , 'legacy' , 'uploaded' ] . includes ( kind )
693+ const invalid = kind === 'malformed' || kind === 'invalid'
694+ const activation = await cli ( 'PATCH' , `/api/v2/files/${ document . id } /share` , {
695+ workspaceId : ws ( ) ,
696+ isActive : true ,
697+ authType : 'public' ,
698+ } )
699+ expect . soft ( activation . status ) . toBe ( allowed ? 200 : invalid ? 500 : 403 )
700+ if ( ! allowed ) expect . soft ( await getShareForResource ( 'file' , document . id ) ) . toBeNull ( )
701+
702+ const humanShare = await updateWorkspaceFileShare . execute ( {
703+ principal : createSessionPrincipal ( { userId : fixture . ids . aliceId } ) ,
704+ input : { fileId : document . id , isActive : true , authType : 'public' } ,
705+ } )
706+ expect ( humanShare . share . isActive ) . toBe ( true )
707+ for ( const read of [ cli , sandbox ] ) {
708+ const link = await read ( 'GET' , `/api/v2/files/${ document . id } /share?workspaceId=${ ws ( ) } ` )
709+ expect . soft ( link . status ) . toBe ( allowed ? 200 : invalid ? 500 : 403 )
710+ if ( ! allowed ) expect . soft ( link . body ) . not . toContain ( humanShare . share . token )
711+ }
712+ if ( ! invalid ) {
713+ const result = await observeContentDelivery (
714+ createRegistryContentGate ( {
715+ registry : new ResolvedSecretTraceRegistry ( [ ] ) ,
716+ actorUserId : fixture . ids . aliceId ,
717+ workspaceId : ws ( ) ,
718+ } ) ,
719+ ( ) =>
720+ getWorkspaceFileShares . execute ( {
721+ principal : createCopilotChatPrincipal (
722+ { userId : fixture . ids . aliceId , workspaceId : ws ( ) } ,
723+ WORKSPACE_FILES_DELEGATION_AUDIENCE
724+ ) ,
725+ input : { workspaceId : ws ( ) , fileIds : [ document . id , fixture . files . clean ] } ,
726+ } )
727+ )
728+ expect ( result . shares . has ( document . id ) ) . toBe ( allowed )
729+ expect ( result . shares . has ( fixture . files . clean ) ) . toBe ( true )
730+ }
731+ }
732+ )
733+
581734 it ( 'reads one file directly: clean as is, secrets redacted, unknown withheld whole (#1, D7)' , async ( ) => {
582735 const download = ( fileId : string ) => cli ( 'GET' , `/api/v2/files/${ fileId } ?workspaceId=${ ws ( ) } ` )
583736 const clean = await download ( fixture . files . clean )
0 commit comments