mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-04 02:12:34 +00:00
Adds the storage substrate for ccsx auth profile isolation. Each Codex profile gets its own CODEX_HOME dir under ~/.ccs/codex-instances/<name>/ with isolated auth.json and history.jsonl; config.toml is shared via symlink to ~/.codex/config.toml so two terminals can run two Codex accounts simultaneously without duplicating user config. - CodexProfileRegistry (YAML, atomic write tmp.<pid>.<rand> + rename, orphan cleanup, full CRUD + default pointer) - decode-id-token: pure base64 JWT decoder for OpenAI id_token, reads nested https://api.openai.com/auth claims (chatgpt_plan_type, chatgpt_account_id) and dual-path email - ensureSharedConfigSymlink: self-healing, idempotent, overwrites stale entries with stderr warning - 45 unit tests, all green Foundation only — no CLI, no runtime injection, no dashboard. Subsequent commits wire those in.
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import * as fs from 'fs';
|
|
import { createLogger } from '../services/logging';
|
|
import { decodeIdToken } from './decode-id-token';
|
|
import type { CodexAccountIdentity } from './types';
|
|
|
|
const logger = createLogger('codex-auth:identity');
|
|
|
|
interface AuthJson {
|
|
tokens?: {
|
|
id_token?: string;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Read auth.json from disk and extract display-safe identity fields.
|
|
* Returns {} on any error (missing file, bad JSON, missing token, decode failure).
|
|
* Never throws.
|
|
*/
|
|
export function decodeAccountIdentity(authJsonPath: string): CodexAccountIdentity {
|
|
try {
|
|
const raw = fs.readFileSync(authJsonPath, 'utf8');
|
|
const parsed = JSON.parse(raw) as AuthJson;
|
|
const idToken = parsed?.tokens?.id_token;
|
|
if (typeof idToken !== 'string' || idToken.length === 0) {
|
|
return {};
|
|
}
|
|
return decodeIdToken(idToken);
|
|
} catch (err) {
|
|
const msg = err instanceof Error ? err.message : String(err);
|
|
logger.warn(
|
|
'codex-auth.identity.decode-failed',
|
|
`Failed to decode account identity from ${authJsonPath}: ${msg}`
|
|
);
|
|
return {};
|
|
}
|
|
}
|