// Writing the delivered OpenAI API key where an OpenAI/Codex client reads it — the consumer half of // model-access for a STATIC-KEY vendor (novox/hq ADR 0050). Unlike the refreshable-grant consumer, // there is nothing to strip: the credential is a single operator-supplied key the mesh sealed to this // holder and the host unsealed at the module's secret path. This process reads that plaintext and // writes it, and only it — no manager, no refresh token, no rotation. // // It is written two ways, for two clients: an `OPENAI_API_KEY=` env file (what most OpenAI // tooling and the OpenAI SDK read), and the publicly-known Codex API-key `auth.json` // (`{ "OPENAI_API_KEY": "" }`). Both are atomic and 0600 — a partial credential must never be // read as a whole one. import { writeFileSync, renameSync, mkdirSync } from "node:fs"; import { dirname } from "node:path"; /** Atomic write-then-rename at 0600, creating the parent directory if needed. */ export function atomicWrite(path: string, content: string): void { mkdirSync(dirname(path), { recursive: true }); const tmp = `${path}.tmp`; writeFileSync(tmp, content, { mode: 0o600 }); renameSync(tmp, path); } /** The Codex API-key auth file shape — the public, documented form of `~/.codex/auth.json`. */ export function authJson(key: string): string { return JSON.stringify({ OPENAI_API_KEY: key }, null, 2) + "\n"; } /** Write the delivered key to both an env file and the Codex auth.json. */ export function deliver(envFile: string, authFile: string, key: string): void { atomicWrite(envFile, `OPENAI_API_KEY=${key}\n`); atomicWrite(authFile, authJson(key)); }