workflow: forward TSX_TSCONFIG_PATH through the worker env scrub
The empty-env hardening wiped the one variable the UNBUILT worker's
loader depends on: tsx finds a tsconfig by searching up from the
worker's cwd, and a parent running outside the repo (the ACP snapshot
harness pins the repo tsconfig through TSX_TSCONFIG_PATH exactly
because its child cwd is a temp dir) lost the dsh-* paths map - the
worker then resolved workspace imports to unbuilt lib/ bundles and died
on CI with ERR_MODULE_NOT_FOUND (green locally only because stale built
lib/ masked the wrong resolution).
Forward exactly that variable when the parent carries it - loader
plumbing, not a secret; the built shape stays fully empty - and pin the
whole contract with an escape-based test: the worker env is exactly
{TSX_TSCONFIG_PATH}, the credential canary still never crosses.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
import { Context } from 'cordis'
|
import { Context } from 'cordis'
|
||||||
import Loader from '@cordisjs/plugin-loader'
|
import Loader from '@cordisjs/plugin-loader'
|
||||||
import { AgentId } from '@deepseek-ai/dsh-agent'
|
import { AgentId } from '@deepseek-ai/dsh-agent'
|
||||||
@@ -272,6 +273,28 @@ describe('dsh-workflow-workerthread', () => {
|
|||||||
delete process.env.WORKFLOW_ENV_CANARY
|
delete process.env.WORKFLOW_ENV_CANARY
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('the unbuilt worker forwards exactly TSX_TSCONFIG_PATH through the scrub: the paths-map pin survives, secrets do not', async () => {
|
||||||
|
const { ctx, parent } = await setup()
|
||||||
|
// The ACP snapshot harness runs the parent with its cwd OUTSIDE the
|
||||||
|
// repo and pins the repo tsconfig through this variable; the worker
|
||||||
|
// must inherit the pin (or its dsh-* imports silently resolve to
|
||||||
|
// unbuilt lib/ bundles) while every other variable stays scrubbed.
|
||||||
|
const tsconfig = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))
|
||||||
|
process.env.TSX_TSCONFIG_PATH = tsconfig
|
||||||
|
process.env.WORKFLOW_ENV_CANARY = 'leak me'
|
||||||
|
try {
|
||||||
|
const result = await run(ctx, parent, scripted(`
|
||||||
|
const proc = ${ESCAPE}
|
||||||
|
return { keys: Object.keys(proc.env), tsconfig: proc.env.TSX_TSCONFIG_PATH }
|
||||||
|
`))
|
||||||
|
expect(result.stopReason).toBe('completed')
|
||||||
|
expect(result.value).toEqual({ keys: ['TSX_TSCONFIG_PATH'], tsconfig })
|
||||||
|
} finally {
|
||||||
|
delete process.env.TSX_TSCONFIG_PATH
|
||||||
|
delete process.env.WORKFLOW_ENV_CANARY
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('lifecycle: parse errors, cancellation, termination, disposal', () => {
|
describe('lifecycle: parse errors, cancellation, termination, disposal', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user