import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, type Stats, } from "node:fs"; /** Audited against @earendil-works/pi-ai 0.80.3 auth plus its locked AWS credential chain. */ export const PI_0803_CREDENTIAL_ENV_NAMES = Object.freeze([ "AI_GATEWAY_API_KEY", "ANTHROPIC_API_KEY", "ANTHROPIC_OAUTH_TOKEN", "ANT_LING_API_KEY", "AWS_ACCESS_KEY_ID", "AWS_BEARER_TOKEN_BEDROCK", "AWS_CONFIG_FILE", "AWS_CONTAINER_AUTHORIZATION_TOKEN", "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE", "AWS_CONTAINER_CREDENTIALS_FULL_URI", "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "AWS_PROFILE", "AWS_ROLE_ARN", "AWS_ROLE_SESSION_NAME", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_SHARED_CREDENTIALS_FILE", "AWS_WEB_IDENTITY_TOKEN_FILE", "AZURE_OPENAI_API_KEY", "CEREBRAS_API_KEY", "CLOUDFLARE_ACCOUNT_ID", "CLOUDFLARE_API_KEY", "CLOUDFLARE_GATEWAY_ID", "COPILOT_GITHUB_TOKEN", "DEEPSEEK_API_KEY", "FIREWORKS_API_KEY", "GCLOUD_PROJECT", "GEMINI_API_KEY", "GOOGLE_APPLICATION_CREDENTIALS", "GOOGLE_CLOUD_API_KEY", "GOOGLE_CLOUD_LOCATION", "GOOGLE_CLOUD_PROJECT", "GROQ_API_KEY", "HF_TOKEN", "KIMI_API_KEY", "MINIMAX_API_KEY", "MINIMAX_CN_API_KEY", "MISTRAL_API_KEY", "MOONSHOT_API_KEY", "NVIDIA_API_KEY", "OPENCODE_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY", "TOGETHER_API_KEY", "XAI_API_KEY", "XIAOMI_API_KEY", "XIAOMI_TOKEN_PLAN_AMS_API_KEY", "XIAOMI_TOKEN_PLAN_CN_API_KEY", "XIAOMI_TOKEN_PLAN_SGP_API_KEY", "ZAI_API_KEY", "ZAI_CODING_CN_API_KEY", ]); const PROVIDER_KEY_ENV: Readonly> = { "ant-ling": "ANT_LING_API_KEY", anthropic: "ANTHROPIC_API_KEY", cerebras: "CEREBRAS_API_KEY", deepseek: "DEEPSEEK_API_KEY", fireworks: "FIREWORKS_API_KEY", "github-copilot": "COPILOT_GITHUB_TOKEN", google: "GEMINI_API_KEY", "google-vertex": "GOOGLE_CLOUD_API_KEY", groq: "GROQ_API_KEY", huggingface: "HF_TOKEN", "kimi-coding": "KIMI_API_KEY", minimax: "MINIMAX_API_KEY", "minimax-cn": "MINIMAX_CN_API_KEY", mistral: "MISTRAL_API_KEY", moonshotai: "MOONSHOT_API_KEY", "moonshotai-cn": "MOONSHOT_API_KEY", nvidia: "NVIDIA_API_KEY", openai: "OPENAI_API_KEY", opencode: "OPENCODE_API_KEY", "opencode-go": "OPENCODE_API_KEY", openrouter: "OPENROUTER_API_KEY", together: "TOGETHER_API_KEY", "vercel-ai-gateway": "AI_GATEWAY_API_KEY", xai: "XAI_API_KEY", xiaomi: "XIAOMI_API_KEY", "xiaomi-token-plan-ams": "XIAOMI_TOKEN_PLAN_AMS_API_KEY", "xiaomi-token-plan-cn": "XIAOMI_TOKEN_PLAN_CN_API_KEY", "xiaomi-token-plan-sgp": "XIAOMI_TOKEN_PLAN_SGP_API_KEY", zai: "ZAI_API_KEY", "zai-coding-cn": "ZAI_CODING_CN_API_KEY", }; const COMPOUND_PROVIDERS = new Set([ "amazon-bedrock", "azure-openai-responses", "cloudflare-ai-gateway", "cloudflare-workers-ai", ]); function configuredCredentialEnv(apiKey: string | undefined): string | null | undefined { if (apiKey === undefined) return undefined; if (!apiKey.startsWith("$")) return null; const matched = /^\$(?:\{([A-Z][A-Z0-9_]*(?:API_KEY|TOKEN))\}|([A-Z][A-Z0-9_]*(?:API_KEY|TOKEN)))$/.exec(apiKey); if (!matched) throw new Error("model provider credential is unavailable"); return matched[1] ?? matched[2]; } export function canonicalPiProvider(provider: string | undefined): string | undefined { const value = provider?.trim().toLowerCase(); if (!value) return undefined; if (value === "gemini") return "google"; return value; } export type PiCredentialStatus = "present" | "missing"; export interface CredentialFsOps { lstat(path: string): Stats; open(path: string, flags: number): number; fstat(fd: number): Stats; read(fd: number): string; close(fd: number): void; } const realFs: CredentialFsOps = { lstat: lstatSync, open: openSync, fstat: fstatSync, read: (fd) => readFileSync(fd, "utf8"), close: closeSync, }; function validSecretStat(info: Stats, docker: boolean): boolean { const mode = info.mode & 0o777; if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > 16_384) return false; if (docker) return info.uid === 0 && mode === 0o444; return info.uid === process.getuid?.() && (mode === 0o400 || mode === 0o600); } function readCredential(file: string, fs: CredentialFsOps): string { let fd: number | undefined; try { const docker = file.startsWith("/run/secrets/") && !file.slice("/run/secrets/".length).includes("/"); if (file.startsWith("/run/secrets/") && !docker) throw new Error(); if (docker) { const parent = fs.lstat("/run/secrets"); if (!parent.isDirectory() || parent.uid !== 0 || (parent.mode & 0o022) !== 0) throw new Error(); } const before = fs.lstat(file); if (!validSecretStat(before, docker)) throw new Error(); fd = fs.open(file, constants.O_RDONLY | constants.O_NOFOLLOW); const opened = fs.fstat(fd); if (!validSecretStat(opened, docker) || before.dev !== opened.dev || before.ino !== opened.ino) throw new Error(); const value = fs.read(fd); if (!value || /\s/.test(value)) throw new Error(); return value; } catch { throw new Error("model provider credential is unavailable"); } finally { if (fd !== undefined) { try { fs.close(fd); } catch { /* sanitized by design */ } } } } export function buildPiChildEnv(opts: { ambient?: NodeJS.ProcessEnv; provider?: string; credentialFile?: string; additions?: NodeJS.ProcessEnv; credentialValue?: string; /** Exact apiKey declaration from the selected provider in models.json. */ configuredApiKey?: string; fsOps?: CredentialFsOps; /** * Providers pi can authenticate from its own auth store. For these, the single * managed key is NOT injected (it belongs to one provider and would misauth the * others); pi resolves the key itself. Empty/absent in deployments without a pi * auth store, keeping the managed-key path authoritative there. */ authProviders?: ReadonlySet; }): NodeJS.ProcessEnv { const env = { ...(opts.ambient ?? process.env), ...opts.additions }; delete env.PI_PROVIDER_API_KEY; delete env.THT_SECRETS_FILE; delete env.THT_DWH_API_KEY; delete env.THT_VEC_API_KEY; delete env.THT_VEC_WRITE_API_KEY; delete env.THT_MODEL_API_KEY; delete env.THT_SSL_CA; delete env.THT_CA; delete env.THT_VECTOR_BOOTSTRAP_PASSWORD; delete env.THT_VECTOR_MIGRATOR_PASSWORD; delete env.THT_VECTOR_READER_PASSWORD; delete env.THT_VECTOR_WRITER_PASSWORD; delete env.THT_MODEL_API_KEY_FILE; delete env.THT_DWH_API_KEY_SECRET_FILE; delete env.THT_VEC_API_KEY_SECRET_FILE; delete env.THT_VEC_WRITE_API_KEY_SECRET_FILE; delete env.THT_CA_SECRET_FILE; delete env.THT_VECTOR_BOOTSTRAP_PASSWORD_SECRET_FILE; delete env.THT_VECTOR_MIGRATOR_PASSWORD_SECRET_FILE; delete env.THT_VECTOR_READER_PASSWORD_SECRET_FILE; delete env.THT_VECTOR_WRITER_PASSWORD_SECRET_FILE; delete env.THT_VECTOR_BOOTSTRAP_PASSWORD_FILE; delete env.THT_VECTOR_MIGRATOR_PASSWORD_FILE; delete env.THT_VECTOR_READER_PASSWORD_FILE; delete env.THT_VECTOR_WRITER_PASSWORD_FILE; delete env.THT_DWH_API_KEY_FILE; delete env.THT_VEC_API_KEY_FILE; delete env.THT_VEC_WRITE_API_KEY_FILE; delete env.THT_SSL_CA_FILE; for (const name of PI_0803_CREDENTIAL_ENV_NAMES) delete env[name]; const provider = canonicalPiProvider(opts.provider); const configuredEnv = configuredCredentialEnv(opts.configuredApiKey); if (configuredEnv) delete env[configuredEnv]; if (provider && COMPOUND_PROVIDERS.has(provider)) { throw new Error( "compound credential bundles are unsupported by THT_MODEL_API_KEY_FILE; " + "dedicated provider configuration is required", ); } if (provider) { // pi self-authenticates this provider from its own auth store; injecting the // single managed key here would force one provider's key onto another. if (opts.authProviders?.has(provider)) return env; // A literal apiKey is entirely owned by models.json (commonly a non-secret // placeholder for a local OpenAI-compatible endpoint) and needs no managed key. if (configuredEnv === null) return env; const envName = configuredEnv ?? PROVIDER_KEY_ENV[provider]; if (!envName || (!opts.credentialFile && opts.credentialValue === undefined)) { throw new Error("model provider credential is unavailable"); } if (opts.credentialValue !== undefined) { if (!opts.credentialValue || /\s/.test(opts.credentialValue)) { throw new Error("model provider credential is unavailable"); } env[envName] = opts.credentialValue; } else if (opts.credentialFile) env[envName] = readCredential(opts.credentialFile, opts.fsOps ?? realFs); else throw new Error("model provider credential is unavailable"); } else if (opts.credentialFile) { throw new Error("model provider credential is unavailable"); } return env; } /** Report only whether the selected hosted provider has a usable credential source. */ export function piProviderCredentialStatus(opts: { provider?: string; credentialFile?: string; resolveCredentialValue?: () => string | undefined; authProviders?: ReadonlySet; configuredApiKey?: string; fsOps?: CredentialFsOps; }): PiCredentialStatus { const provider = canonicalPiProvider(opts.provider); if (!provider) return "missing"; if (opts.authProviders?.has(provider)) return "present"; const configuredEnv = configuredCredentialEnv(opts.configuredApiKey); if (configuredEnv === null) return "missing"; try { buildPiChildEnv({ ambient: {}, provider, credentialFile: opts.credentialFile, credentialValue: opts.resolveCredentialValue?.(), authProviders: opts.authProviders, configuredApiKey: opts.configuredApiKey, fsOps: opts.fsOps, }); return "present"; } catch { return "missing"; } }