fix: remove Codex API key auth path, add secret redaction and d7 auto-rotation

- Remove OPENAI_API_KEY from .env and Codex child process env to prevent
  API billing when subscription quota is exhausted
- Remove writeCodexApiKeyAuth entirely — Codex now uses OAuth only
- Add 9-pattern secret redaction in formatOutbound() to prevent key leaks
- Fix Codex usage bucket aggregation: use 'codex' bucket only instead of
  max across all buckets (bengalfox = Codex Spark, not needed)
- Add d7≥100% auto-rotation in updateCodexAccountUsage to skip exhausted
  accounts and prevent API billing fallback
- Add findNextCodexAvailable that checks both rate-limits and d7 usage
- Clean stale apikey auth.json files from all session directories
- Update tests: OAuth-only auth, d7 auto-skip (3 new tests), dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eyejoker
2026-03-25 10:39:42 +09:00
parent 094278b08e
commit 00ffde7623
11 changed files with 818 additions and 192 deletions

View File

@@ -20,19 +20,8 @@ import {
} from './platform-prompts.js';
import type { AgentType, RegisteredGroup } from './types.js';
function writeCodexApiKeyAuth(authPath: string, openaiKey: string): void {
fs.writeFileSync(
authPath,
JSON.stringify(
{
auth_mode: 'apikey',
OPENAI_API_KEY: openaiKey,
},
null,
2,
) + '\n',
);
}
// writeCodexApiKeyAuth removed — Codex uses OAuth only.
// API key auth caused unintended billing.
function syncDirectoryEntries(sources: string[], destination: string): void {
for (const source of sources) {
@@ -184,12 +173,10 @@ function prepareCodexSessionEnvironment(args: {
isPairedRoom: boolean;
memoryBriefing?: string;
}): void {
const openaiKey =
args.envVars.CODEX_OPENAI_API_KEY ||
process.env.CODEX_OPENAI_API_KEY ||
args.envVars.OPENAI_API_KEY ||
process.env.OPENAI_API_KEY;
if (openaiKey) args.env.OPENAI_API_KEY = openaiKey;
// API key auth intentionally removed — Codex uses OAuth only.
// Never pass any API key to Codex child process to prevent API billing.
delete args.env.OPENAI_API_KEY;
delete args.env.CODEX_OPENAI_API_KEY;
const codexModel =
args.group.agentConfig?.codexModel ||
@@ -208,9 +195,8 @@ function prepareCodexSessionEnvironment(args: {
fs.mkdirSync(sessionCodexDir, { recursive: true });
const authDst = path.join(sessionCodexDir, 'auth.json');
if (openaiKey) {
writeCodexApiKeyAuth(authDst, openaiKey);
} else {
// Always use OAuth auth from rotated accounts (API key auth removed)
{
const rotatedAuthSrc = getActiveCodexAuthPath();
const authSrc =
rotatedAuthSrc && fs.existsSync(rotatedAuthSrc)
@@ -417,8 +403,6 @@ export function prepareGroupEnvironment(
'CLAUDE_THINKING',
'CLAUDE_THINKING_BUDGET',
'CLAUDE_EFFORT',
'OPENAI_API_KEY',
'CODEX_OPENAI_API_KEY',
'CODEX_MODEL',
'CODEX_EFFORT',
'MEMENTO_MCP_SSE_URL',