@@ -123,6 +123,7 @@ describe('executeWorkflowCore terminal finalization sequencing', () => {
123123 requestId : 'req-1' ,
124124 workflowId : 'workflow-1' ,
125125 userId : 'user-1' ,
126+ workflowUserId : 'workflow-owner' ,
126127 workspaceId : 'workspace-1' ,
127128 triggerType : 'api' ,
128129 executionId : 'execution-1' ,
@@ -755,4 +756,92 @@ describe('executeWorkflowCore terminal finalization sequencing', () => {
755756 expect ( safeCompleteWithErrorMock ) . not . toHaveBeenCalled ( )
756757 expect ( wasExecutionFinalizedByCore ( envError , 'execution-no-log-start' ) ) . toBe ( false )
757758 } )
759+
760+ it ( 'uses sessionUserId for env resolution when isClientSession is true' , async ( ) => {
761+ const snapshot = {
762+ ...createSnapshot ( ) ,
763+ metadata : {
764+ ...createSnapshot ( ) . metadata ,
765+ isClientSession : true ,
766+ sessionUserId : 'session-user' ,
767+ workflowUserId : 'workflow-owner' ,
768+ } ,
769+ }
770+
771+ getPersonalAndWorkspaceEnvMock . mockResolvedValue ( {
772+ personalEncrypted : { } ,
773+ workspaceEncrypted : { } ,
774+ personalDecrypted : { } ,
775+ workspaceDecrypted : { } ,
776+ } )
777+ safeStartMock . mockResolvedValue ( true )
778+ executorExecuteMock . mockResolvedValue ( {
779+ output : { done : true } ,
780+ logs : [ ] ,
781+ metadata : { duration : 123 , startTime : 'start' , endTime : 'end' } ,
782+ } )
783+
784+ await executeWorkflowCore ( {
785+ snapshot : snapshot as any ,
786+ callbacks : { } ,
787+ loggingSession : loggingSession as any ,
788+ } )
789+
790+ expect ( getPersonalAndWorkspaceEnvMock ) . toHaveBeenCalledWith ( 'session-user' , 'workspace-1' )
791+ } )
792+
793+ it ( 'uses workflowUserId for env resolution in server-side execution' , async ( ) => {
794+ const snapshot = {
795+ ...createSnapshot ( ) ,
796+ metadata : {
797+ ...createSnapshot ( ) . metadata ,
798+ isClientSession : false ,
799+ sessionUserId : undefined ,
800+ workflowUserId : 'workflow-owner' ,
801+ userId : 'billing-actor' ,
802+ } ,
803+ }
804+
805+ getPersonalAndWorkspaceEnvMock . mockResolvedValue ( {
806+ personalEncrypted : { } ,
807+ workspaceEncrypted : { } ,
808+ personalDecrypted : { } ,
809+ workspaceDecrypted : { } ,
810+ } )
811+ safeStartMock . mockResolvedValue ( true )
812+ executorExecuteMock . mockResolvedValue ( {
813+ output : { done : true } ,
814+ logs : [ ] ,
815+ metadata : { duration : 123 , startTime : 'start' , endTime : 'end' } ,
816+ } )
817+
818+ await executeWorkflowCore ( {
819+ snapshot : snapshot as any ,
820+ callbacks : { } ,
821+ loggingSession : loggingSession as any ,
822+ } )
823+
824+ expect ( getPersonalAndWorkspaceEnvMock ) . toHaveBeenCalledWith ( 'workflow-owner' , 'workspace-1' )
825+ } )
826+
827+ it ( 'throws when workflowUserId is missing in server-side execution' , async ( ) => {
828+ const snapshot = {
829+ ...createSnapshot ( ) ,
830+ metadata : {
831+ ...createSnapshot ( ) . metadata ,
832+ isClientSession : false ,
833+ sessionUserId : undefined ,
834+ workflowUserId : undefined ,
835+ userId : 'billing-actor' ,
836+ } ,
837+ }
838+
839+ await expect (
840+ executeWorkflowCore ( {
841+ snapshot : snapshot as any ,
842+ callbacks : { } ,
843+ loggingSession : loggingSession as any ,
844+ } )
845+ ) . rejects . toThrow ( 'Missing workflowUserId in execution metadata' )
846+ } )
758847} )
0 commit comments