type RuntimeAwareSystemSettings = { aiProvider?: string | null; azureOpenAiApiKey?: string | null; azureDalleApiKey?: string | null; geminiApiKey?: string | null; smtpPassword?: string | null; smtpHost?: string | null; smtpPort?: number | null; smtpUser?: string | null; smtpFrom?: string | null; smtpTls?: boolean | null; anonymizationSeed?: string | null; }; export const RUNTIME_SECRET_FIELDS = [ "azureOpenAiApiKey", "azureDalleApiKey", "geminiApiKey", "smtpPassword", "anonymizationSeed", ] as const; export type RuntimeSecretField = (typeof RUNTIME_SECRET_FIELDS)[number]; export type RuntimeSecretStatus = { configured: boolean; activeSource: "environment" | "database" | "none"; hasStoredValue: boolean; envVarNames: string[]; }; function readEnvOverride(...names: string[]): string | null { for (const name of names) { const value = process.env[name]?.trim(); if (value) { return value; } } return null; } function resolvePrimaryAiApiKey(provider: string | null | undefined): string | null { if (provider === "azure") { return readEnvOverride("AZURE_OPENAI_API_KEY", "OPENAI_API_KEY"); } return readEnvOverride("OPENAI_API_KEY", "AZURE_OPENAI_API_KEY"); } function getPrimaryAiEnvVarNames(provider: string | null | undefined): string[] { if (provider === "azure") { return ["AZURE_OPENAI_API_KEY", "OPENAI_API_KEY"]; } return ["OPENAI_API_KEY", "AZURE_OPENAI_API_KEY"]; } function resolveSecretEnvOverride( field: RuntimeSecretField, provider: string | null | undefined, ): string | null { if (field === "azureOpenAiApiKey") { return resolvePrimaryAiApiKey(provider); } if (field === "azureDalleApiKey") { return readEnvOverride("AZURE_DALLE_API_KEY"); } if (field === "geminiApiKey") { return readEnvOverride("GEMINI_API_KEY"); } if (field === "smtpPassword") { return readEnvOverride("SMTP_PASSWORD"); } return readEnvOverride("ANONYMIZATION_SEED"); } function getSecretEnvVarNames( field: RuntimeSecretField, provider: string | null | undefined, ): string[] { if (field === "azureOpenAiApiKey") { return getPrimaryAiEnvVarNames(provider); } if (field === "azureDalleApiKey") { return ["AZURE_DALLE_API_KEY"]; } if (field === "geminiApiKey") { return ["GEMINI_API_KEY"]; } if (field === "smtpPassword") { return ["SMTP_PASSWORD"]; } return ["ANONYMIZATION_SEED"]; } export function getRuntimeSecretStatuses( settings: RuntimeAwareSystemSettings | null | undefined, ): Record { const provider = settings?.aiProvider; return Object.fromEntries( RUNTIME_SECRET_FIELDS.map((field) => { const envValue = resolveSecretEnvOverride(field, provider); const storedValue = settings?.[field]?.trim() || null; const activeSource = envValue ? "environment" : storedValue ? "database" : "none"; return [ field, { configured: !!(envValue || storedValue), activeSource, hasStoredValue: !!storedValue, envVarNames: getSecretEnvVarNames(field, provider), } satisfies RuntimeSecretStatus, ]; }), ) as Record; } /** Resolve non-secret SMTP fields from ENV (take precedence over DB). */ function resolveSmtpNonSecretOverrides(settings: RuntimeAwareSystemSettings | null | undefined): { smtpHost: string | null; smtpPort: number | null; smtpUser: string | null; smtpFrom: string | null; smtpTls: boolean | null; } { const envHost = readEnvOverride("SMTP_HOST"); const envPort = readEnvOverride("SMTP_PORT"); const envUser = readEnvOverride("SMTP_USER"); const envFrom = readEnvOverride("SMTP_FROM"); const envTlsRaw = process.env["SMTP_TLS"]?.trim(); return { smtpHost: envHost ?? settings?.smtpHost ?? null, smtpPort: envPort !== null ? parseInt(envPort, 10) : settings?.smtpPort ?? null, smtpUser: envUser ?? settings?.smtpUser ?? null, smtpFrom: envFrom ?? settings?.smtpFrom ?? null, smtpTls: envTlsRaw !== undefined ? envTlsRaw !== "false" : settings?.smtpTls ?? null, }; } export function resolveSystemSettingsRuntime( settings: T | null | undefined, ): T & Required> { const resolved = { ...(settings ?? {}) } as T & Required>; resolved.azureOpenAiApiKey = resolveSecretEnvOverride("azureOpenAiApiKey", resolved.aiProvider) ?? settings?.azureOpenAiApiKey ?? null; resolved.azureDalleApiKey = resolveSecretEnvOverride("azureDalleApiKey", resolved.aiProvider) ?? settings?.azureDalleApiKey ?? null; resolved.geminiApiKey = resolveSecretEnvOverride("geminiApiKey", resolved.aiProvider) ?? settings?.geminiApiKey ?? null; resolved.smtpPassword = resolveSecretEnvOverride("smtpPassword", resolved.aiProvider) ?? settings?.smtpPassword ?? null; resolved.anonymizationSeed = resolveSecretEnvOverride("anonymizationSeed", resolved.aiProvider) ?? settings?.anonymizationSeed ?? null; const smtpOverrides = resolveSmtpNonSecretOverrides(settings); resolved.smtpHost = smtpOverrides.smtpHost; resolved.smtpPort = smtpOverrides.smtpPort; resolved.smtpUser = smtpOverrides.smtpUser; resolved.smtpFrom = smtpOverrides.smtpFrom; resolved.smtpTls = smtpOverrides.smtpTls; return resolved; }