( ref: RawKeyRef, env: EnvLookup, ctx: ResolveKeyContext )
| 327 | } |
| 328 | |
| 329 | async function resolveKey( |
| 330 | ref: RawKeyRef, |
| 331 | env: EnvLookup, |
| 332 | ctx: ResolveKeyContext |
| 333 | ): Promise<{ key: string | null; source: KeySource; envVarFailed: boolean }> { |
| 334 | if (!isEnvVarReference(ref.rawValue)) { |
| 335 | return { key: ref.rawValue, source: 'plaintext', envVarFailed: false } |
| 336 | } |
| 337 | |
| 338 | const varName = extractEnvVarName(ref.rawValue) |
| 339 | if (!varName) return { key: null, source: 'personal', envVarFailed: true } |
| 340 | |
| 341 | const personalVars = env.personalEnvCache.get(ref.userId) |
| 342 | |
| 343 | const wsValue = env.wsEnvVars[varName] |
| 344 | const personalValue = personalVars?.[varName] |
| 345 | const encryptedValue = wsValue ?? personalValue |
| 346 | const source: KeySource = wsValue ? 'workspace' : 'personal' |
| 347 | |
| 348 | const logPrefix = |
| 349 | `workspace=${ctx.workspaceId} owner=${ctx.workspaceOwnerId ?? 'unknown'}` + |
| 350 | ` workflow=${ref.workflowId} user=${ref.userId}` |
| 351 | |
| 352 | if (!encryptedValue) { |
| 353 | console.warn( |
| 354 | ` [WARN] Env var "${varName}" not found — ${logPrefix} "${ref.blockName}" in "${ref.workflowName}"` |
| 355 | ) |
| 356 | return { key: null, source, envVarFailed: true } |
| 357 | } |
| 358 | |
| 359 | try { |
| 360 | const decrypted = await decryptSecret(encryptedValue) |
| 361 | return { key: decrypted, source, envVarFailed: false } |
| 362 | } catch (error) { |
| 363 | console.warn( |
| 364 | ` [WARN] Failed to decrypt env var "${varName}" — ${logPrefix} "${ref.blockName}" in "${ref.workflowName}": ${error}` |
| 365 | ) |
| 366 | return { key: null, source, envVarFailed: true } |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | async function processWorkspace( |
| 371 | workspaceId: string, |
no test coverage detected