import type { KeychainData } from '../credentials/keychain.js'; import type { StoredAccountPrefs } from '../switching/preferences.js'; /** * On-disk shape of `~/.claude/accounts/.json`. * * It is Claude Code's `oauthAccount` block (emailAddress + assorted fields the * binary writes — accountUuid, organization, … left untyped via the index * signature) plus claude-switch's internal snapshot fields, all `_`-prefixed. * * This interface is the single source of truth for those internal field names. * A field added to `accounts.save()` must be added here; TypeScript then flags * every reader (`accounts.load()`, migration, `apikey`, `usage`, `profiles`) * that forgot it — closing the "added on write, dropped on read" drift class. */ export interface AccountSnapshot { emailAddress?: string; /** OAuth + API-key credentials captured from the Keychain (macOS) or JSON. */ _keychain?: KeychainData; /** Per-account API key used as fallback when subscription limits are hit. */ _apiKey?: string; /** Per-account preferences embedded in the snapshot. */ _prefs?: StoredAccountPrefs; /** Snapshot of Claude Code's `customApiKeyResponses` to stop cross-account leak. */ _customApiKeyResponses?: unknown; /** API key the binary wrote top-level into `~/.claude.json` (billing-leak guard). */ _claudeJsonApiKey?: string; /** * Provenance of the captured `_keychain` block (23.6). Populated by `save()` * when the live Keychain read returned a payload, with the `accountUuid` and * `emailAddress` taken from claude.json's `oauthAccount` at capture time — * i.e. the account the Keychain tokens actually belong to. * * `load()` cross-checks `_capturedFrom.accountUuid` against the snapshot's * own `accountUuid`; a mismatch means the snapshot was poisoned by a * pre-23.5 save() that captured tokens under the wrong account. Such * snapshots have their Keychain restore skipped (see load()). * * Absent on snapshots written by older claude-switch versions — that case * is the legacy path, treated as "unknown provenance, trust the file". */ _capturedFrom?: { emailAddress?: string; accountUuid?: string; /** Epoch milliseconds — set via `Date.now()` at save() time. */ capturedAt?: number; }; [k: string]: unknown; }