fix(envvars): restore workflowUserId fallback for scheduled execution env var resolution (#3941)

* fix(envvars): restore workflowUserId fallback for scheduled execution env var resolution

* test(envvars): add coverage for env var user resolution branches
This commit is contained in:
Waleed
2026-04-04 11:22:52 -07:00
committed by GitHub
parent b0cb95be2f
commit 893e322a49
2 changed files with 94 additions and 2 deletions

View File

@@ -123,6 +123,7 @@ describe('executeWorkflowCore terminal finalization sequencing', () => {
requestId: 'req-1',
workflowId: 'workflow-1',
userId: 'user-1',
workflowUserId: 'workflow-owner',
workspaceId: 'workspace-1',
triggerType: 'api',
executionId: 'execution-1',
@@ -755,4 +756,92 @@ describe('executeWorkflowCore terminal finalization sequencing', () => {
expect(safeCompleteWithErrorMock).not.toHaveBeenCalled()
expect(wasExecutionFinalizedByCore(envError, 'execution-no-log-start')).toBe(false)
})
it('uses sessionUserId for env resolution when isClientSession is true', async () => {
const snapshot = {
...createSnapshot(),
metadata: {
...createSnapshot().metadata,
isClientSession: true,
sessionUserId: 'session-user',
workflowUserId: 'workflow-owner',
},
}
getPersonalAndWorkspaceEnvMock.mockResolvedValue({
personalEncrypted: {},
workspaceEncrypted: {},
personalDecrypted: {},
workspaceDecrypted: {},
})
safeStartMock.mockResolvedValue(true)
executorExecuteMock.mockResolvedValue({
output: { done: true },
logs: [],
metadata: { duration: 123, startTime: 'start', endTime: 'end' },
})
await executeWorkflowCore({
snapshot: snapshot as any,
callbacks: {},
loggingSession: loggingSession as any,
})
expect(getPersonalAndWorkspaceEnvMock).toHaveBeenCalledWith('session-user', 'workspace-1')
})
it('uses workflowUserId for env resolution in server-side execution', async () => {
const snapshot = {
...createSnapshot(),
metadata: {
...createSnapshot().metadata,
isClientSession: false,
sessionUserId: undefined,
workflowUserId: 'workflow-owner',
userId: 'billing-actor',
},
}
getPersonalAndWorkspaceEnvMock.mockResolvedValue({
personalEncrypted: {},
workspaceEncrypted: {},
personalDecrypted: {},
workspaceDecrypted: {},
})
safeStartMock.mockResolvedValue(true)
executorExecuteMock.mockResolvedValue({
output: { done: true },
logs: [],
metadata: { duration: 123, startTime: 'start', endTime: 'end' },
})
await executeWorkflowCore({
snapshot: snapshot as any,
callbacks: {},
loggingSession: loggingSession as any,
})
expect(getPersonalAndWorkspaceEnvMock).toHaveBeenCalledWith('workflow-owner', 'workspace-1')
})
it('throws when workflowUserId is missing in server-side execution', async () => {
const snapshot = {
...createSnapshot(),
metadata: {
...createSnapshot().metadata,
isClientSession: false,
sessionUserId: undefined,
workflowUserId: undefined,
userId: 'billing-actor',
},
}
await expect(
executeWorkflowCore({
snapshot: snapshot as any,
callbacks: {},
loggingSession: loggingSession as any,
})
).rejects.toThrow('Missing workflowUserId in execution metadata')
})
})

View File

@@ -325,10 +325,13 @@ export async function executeWorkflowCore(
const mergedStates = mergeSubblockStateWithValues(blocks)
const personalEnvUserId = metadata.sessionUserId || metadata.userId
const personalEnvUserId =
metadata.isClientSession && metadata.sessionUserId
? metadata.sessionUserId
: metadata.workflowUserId
if (!personalEnvUserId) {
throw new Error('Missing execution actor for environment resolution')
throw new Error('Missing workflowUserId in execution metadata')
}
const { personalEncrypted, workspaceEncrypted, personalDecrypted, workspaceDecrypted } =