fix(invariants): join package checks at startup
This commit is contained in:
@@ -12,15 +12,12 @@ export const name = 'subagent-inprocess-invariant'
|
||||
export const inject = ['invariants']
|
||||
|
||||
/** Assert that structured-output guidance names the tool it actually installs. */
|
||||
const install: InvariantInstaller = (ctx, fail) => {
|
||||
ctx.effect(async () => {
|
||||
const { STRUCTURED_OUTPUT_INSTRUCTION, STRUCTURED_OUTPUT_TOOL } = await import('./structured-protocol.ts')
|
||||
assertInvariant(fail, /^[a-z][a-z0-9_]*$/.test(STRUCTURED_OUTPUT_TOOL),
|
||||
'the structured-output tool must retain a stable lowercase protocol name')
|
||||
assertInvariant(fail, STRUCTURED_OUTPUT_INSTRUCTION.includes(STRUCTURED_OUTPUT_TOOL),
|
||||
'the structured-output instruction must name the exact installed tool')
|
||||
return () => {}
|
||||
}, 'subagent-inprocess: validate structured-output protocol')
|
||||
const install: InvariantInstaller = async (_ctx, fail) => {
|
||||
const { STRUCTURED_OUTPUT_INSTRUCTION, STRUCTURED_OUTPUT_TOOL } = await import('./structured-protocol.ts')
|
||||
assertInvariant(fail, /^[a-z][a-z0-9_]*$/.test(STRUCTURED_OUTPUT_TOOL),
|
||||
'the structured-output tool must retain a stable lowercase protocol name')
|
||||
assertInvariant(fail, STRUCTURED_OUTPUT_INSTRUCTION.includes(STRUCTURED_OUTPUT_TOOL),
|
||||
'the structured-output instruction must name the exact installed tool')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,19 +13,24 @@ export const name = 'subagent-subprocess-invariant'
|
||||
export const inject = ['invariants']
|
||||
|
||||
/** Assert ambient credential scrubbing and explicit credential precedence. */
|
||||
const install: InvariantInstaller = (ctx, fail) => {
|
||||
ctx.effect(async () => {
|
||||
const { buildChildEnv } = await import('./index.ts')
|
||||
const scrubbed = buildChildEnv({})
|
||||
const ambientSensitiveNames = Object.keys(process.env).filter(key => SENSITIVE_ENV_PATTERN.test(key))
|
||||
assertInvariant(fail, ambientSensitiveNames.every(key => !Object.hasOwn(scrubbed, key)),
|
||||
'subprocess environments must omit every credential-shaped ambient variable')
|
||||
const install: InvariantInstaller = async (_ctx, fail) => {
|
||||
const { buildChildEnv } = await import('./index.ts')
|
||||
const ambientProbe = `DSH_INVARIANT_AMBIENT_TOKEN_${process.pid}`
|
||||
assertInvariant(fail, SENSITIVE_ENV_PATTERN.test(ambientProbe),
|
||||
'the invariant ambient probe must remain credential-shaped')
|
||||
process.env[ambientProbe] = 'must-not-reach-child'
|
||||
let scrubbed: NodeJS.ProcessEnv
|
||||
try {
|
||||
scrubbed = buildChildEnv({})
|
||||
} finally {
|
||||
Reflect.deleteProperty(process.env, ambientProbe)
|
||||
}
|
||||
assertInvariant(fail, !Object.hasOwn(scrubbed, ambientProbe),
|
||||
'subprocess environments must omit every credential-shaped ambient variable')
|
||||
|
||||
const explicit = buildChildEnv({ DSH_INVARIANT_TOKEN: 'explicit-child-value' })
|
||||
assertInvariant(fail, explicit.DSH_INVARIANT_TOKEN === 'explicit-child-value',
|
||||
'explicit child credentials must be applied after ambient scrubbing')
|
||||
return () => {}
|
||||
}, 'subagent-subprocess: validate child environment isolation')
|
||||
const explicit = buildChildEnv({ DSH_INVARIANT_TOKEN: 'explicit-child-value' })
|
||||
assertInvariant(fail, explicit.DSH_INVARIANT_TOKEN === 'explicit-child-value',
|
||||
'explicit child credentials must be applied after ambient scrubbing')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user