Files
steipete--codexbar/Tests/CodexBarTests/TokenAccountEnvironmentPrecedenceTests.swift
2026-07-13 12:22:33 +08:00

1238 lines
52 KiB
Swift

import CodexBarCore
import Foundation
import Testing
@testable import CodexBar
@testable import CodexBarCLI
@Suite(.serialized)
struct AlibabaTokenPlanRegionSelectionTests {
@Test @MainActor
func `fresh app settings default to International`() {
let settings = testSettingsStore(suiteName: "AlibabaTokenPlanRegionSelectionTests-fresh")
#expect(settings.alibabaTokenPlanAPIRegion == .international)
}
@Test @MainActor
func `legacy app settings without region remain China mainland`() {
var config = CodexBarConfig.makeDefault()
config.setProviderConfig(ProviderConfig(id: .alibabatokenplan, region: nil))
let settings = testSettingsStore(
suiteName: "AlibabaTokenPlanRegionSelectionTests-legacy",
config: config)
#expect(settings.alibabaTokenPlanAPIRegion == .chinaMainland)
}
@Test @MainActor
func `app settings trim configured region`() {
var config = CodexBarConfig.makeDefault()
config.setProviderConfig(ProviderConfig(id: .alibabatokenplan, region: " intl "))
let settings = testSettingsStore(
suiteName: "AlibabaTokenPlanRegionSelectionTests-trimmed",
config: config)
#expect(settings.alibabaTokenPlanAPIRegion == .international)
}
@Test
func `CLI honors explicit region and keeps legacy config on China mainland`() throws {
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let internationalContext = try TokenAccountCLIContext(
selection: selection,
config: CodexBarConfig(providers: [
ProviderConfig(id: .alibabatokenplan, region: AlibabaTokenPlanAPIRegion.international.rawValue),
]),
verbose: false)
let legacyContext = try TokenAccountCLIContext(
selection: selection,
config: CodexBarConfig(providers: [
ProviderConfig(id: .alibabatokenplan, region: nil),
]),
verbose: false)
#expect(internationalContext.settingsSnapshot(for: .alibabatokenplan, account: nil)?
.alibabaTokenPlan?.apiRegion == .international)
#expect(legacyContext.settingsSnapshot(for: .alibabatokenplan, account: nil)?
.alibabaTokenPlan?.apiRegion == .chinaMainland)
}
}
@Suite(.serialized)
struct ZaiTokenAccountEnvironmentPrecedenceTests {
@Test
func `zai CLI settings snapshot defaults to personal without account scope`() throws {
let config = CodexBarConfig(providers: [
ProviderConfig(id: .zai),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(
selection: selection,
config: config,
verbose: false,
baseEnvironment: [
ZaiSettingsReader.bigModelOrganizationKey: " org-env ",
ZaiSettingsReader.bigModelProjectKey: " proj-env ",
])
let snapshot = try #require(tokenContext.settingsSnapshot(for: .zai, account: nil)?.zai)
#expect(snapshot.usageScope == .personal)
#expect(snapshot.teamContext == nil)
}
@Test
func `zai CLI settings snapshot uses selected team account scope`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "Team",
token: "account-token",
addedAt: 0,
lastUsed: nil,
usageScope: " team ",
organizationID: " org-account ",
workspaceID: " proj-account ")
let config = CodexBarConfig(providers: [
ProviderConfig(id: .zai),
])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false,
baseEnvironment: [
ZaiSettingsReader.bigModelOrganizationKey: "org-env",
ZaiSettingsReader.bigModelProjectKey: "proj-env",
])
let snapshot = try #require(tokenContext.settingsSnapshot(for: .zai, account: account)?.zai)
#expect(snapshot.usageScope == .team)
#expect(snapshot.teamContext?.organizationID == "org-account")
#expect(snapshot.teamContext?.projectID == "proj-account")
}
@Test
func `zai CLI personal account scope clears inherited team context`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "Personal",
token: "account-token",
addedAt: 0,
lastUsed: nil,
usageScope: "personal")
let config = CodexBarConfig(providers: [
ProviderConfig(id: .zai),
])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false,
baseEnvironment: [
ZaiSettingsReader.bigModelOrganizationKey: "org-env",
ZaiSettingsReader.bigModelProjectKey: "proj-env",
])
let snapshot = try #require(tokenContext.settingsSnapshot(for: .zai, account: account)?.zai)
#expect(snapshot.usageScope == .personal)
#expect(snapshot.teamContext == nil)
}
}
@Suite(.serialized)
@MainActor
struct TokenAccountEnvironmentPrecedenceTests {
@Test
func `token account environment overrides config API key in app environment builder`() {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-app")
settings.zaiAPIToken = "config-token"
settings.addTokenAccount(provider: .zai, label: "Account 1", token: "account-token")
let env = ProviderRegistry.makeEnvironment(
base: ["FOO": "bar"],
provider: .zai,
settings: settings,
tokenOverride: nil)
#expect(env["FOO"] == "bar")
#expect(env[ZaiSettingsReader.apiTokenKey] == "account-token")
#expect(env[ZaiSettingsReader.apiTokenKey] != "config-token")
}
@Test
func `deepseek token account injects environment in app environment builder`() {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-deepseek-app")
settings.addTokenAccount(provider: .deepseek, label: "Account 1", token: "account-token")
let env = ProviderRegistry.makeEnvironment(
base: ["FOO": "bar"],
provider: .deepseek,
settings: settings,
tokenOverride: nil)
#expect(env["FOO"] == "bar")
#expect(env[DeepSeekSettingsReader.apiKeyEnvironmentKey] == "account-token")
}
@Test
func `token account environment overrides config API key in CLI environment builder`() throws {
let config = CodexBarConfig(
providers: [
ProviderConfig(id: .zai, apiKey: "config-token"),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = ProviderTokenAccount(
id: UUID(),
label: "Account 1",
token: "account-token",
addedAt: Date().timeIntervalSince1970,
lastUsed: nil)
let env = tokenContext.environment(base: [:], provider: .zai, account: account)
#expect(env[ZaiSettingsReader.apiTokenKey] == "account-token")
#expect(env[ZaiSettingsReader.apiTokenKey] != "config-token")
}
@Test
func `deepseek token account injects environment in CLI environment builder`() throws {
let config = CodexBarConfig(providers: [])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = ProviderTokenAccount(
id: UUID(),
label: "Account 1",
token: "account-token",
addedAt: Date().timeIntervalSince1970,
lastUsed: nil)
let env = tokenContext.environment(base: [:], provider: .deepseek, account: account)
#expect(env[DeepSeekSettingsReader.apiKeyEnvironmentKey] == "account-token")
}
@Test
func `ollama token account selection forces manual cookie source in CLI settings snapshot`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "session=account-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .ollama,
cookieSource: .auto,
tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .ollama).first)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .ollama, account: account))
let ollamaSettings = try #require(snapshot.ollama)
#expect(ollamaSettings.cookieSource == .manual)
#expect(ollamaSettings.manualCookieHeader == "session=account-token")
}
@Test
func `command code config cookie is carried into CLI settings snapshot`() throws {
let config = CodexBarConfig(providers: [
ProviderConfig(
id: .commandcode,
cookieHeader: "better-auth.session_token=manual-token",
cookieSource: .manual),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .commandcode, account: nil))
let commandCodeSettings = try #require(snapshot.commandcode)
#expect(commandCodeSettings.cookieSource == .manual)
#expect(commandCodeSettings.manualCookieHeader == "better-auth.session_token=manual-token")
}
@Test
func `app snapshot override resolves cookie account without mutating stored selection`() throws {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-cookie-override-app")
settings.cursorCookieSource = .auto
settings.cursorCookieHeader = "configured=true"
let account = ProviderTokenAccount(
id: UUID(),
label: "Override",
token: "account=true",
addedAt: 0,
lastUsed: nil)
let snapshot = ProviderRegistry.makeSettingsSnapshot(
settings: settings,
tokenOverride: TokenAccountOverride(provider: .cursor, account: account))
let cursorSettings = try #require(snapshot.cursor)
#expect(cursorSettings.cookieSource == .manual)
#expect(cursorSettings.manualCookieHeader == "account=true")
#expect(settings.tokenAccounts(for: .cursor).isEmpty)
}
@Test
func `stepfun CLI snapshot reads manual token from region field`() throws {
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .stepfun,
region: "Oasis-Token=manual-token; Oasis-Webid=web"),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .stepfun, account: nil))
let stepfunSettings = try #require(snapshot.stepfun)
#expect(stepfunSettings.cookieSource == .manual)
#expect(stepfunSettings.manualToken == "Oasis-Token=manual-token; Oasis-Webid=web")
}
@Test
func `stepfun CLI token account overrides region manual token`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "StepFun",
token: "account-token",
addedAt: Date().timeIntervalSince1970,
lastUsed: nil)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .stepfun,
region: "manual-token",
tokenAccounts: ProviderTokenAccountData(
version: 1,
accounts: [account],
activeIndex: 0)),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let resolvedAccount = try #require(tokenContext.resolvedAccounts(for: .stepfun).first)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .stepfun, account: resolvedAccount))
let stepfunSettings = try #require(snapshot.stepfun)
#expect(stepfunSettings.cookieSource == .manual)
#expect(stepfunSettings.manualToken == "account-token")
}
@Test
func `claude OAuth token account overrides environment in app environment builder`() {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-claude-app")
settings.addTokenAccount(provider: .claude, label: "OAuth", token: "Bearer sk-ant-oat-account-token")
let env = ProviderRegistry.makeEnvironment(
base: ["FOO": "bar"],
provider: .claude,
settings: settings,
tokenOverride: nil)
#expect(env["FOO"] == "bar")
#expect(env[ClaudeOAuthCredentialsStore.environmentTokenKey] == "sk-ant-oat-account-token")
}
@Test
func `claude session account strips ambient admin api credentials in app environment builder`() {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-claude-admin-strip-app")
settings.claudeAdminAPIKey = "sk-ant-admin-config"
settings.addTokenAccount(provider: .claude, label: "Session", token: "sk-ant-session-token")
let env = ProviderRegistry.makeEnvironment(
base: [
"FOO": "bar",
ClaudeAdminAPISettingsReader.alternateAdminAPIKeyEnvironmentKey: "sk-ant-admin-base",
ClaudeOAuthCredentialsStore.environmentTokenKey: "sk-ant-oat-base",
],
provider: .claude,
settings: settings,
tokenOverride: nil)
#expect(env["FOO"] == "bar")
#expect(env[ClaudeAdminAPISettingsReader.adminAPIKeyEnvironmentKey] == nil)
#expect(env[ClaudeAdminAPISettingsReader.alternateAdminAPIKeyEnvironmentKey] == nil)
#expect(env[ClaudeOAuthCredentialsStore.environmentTokenKey] == nil)
}
@Test
func `claude session key selection carries organization id in app settings snapshot`() throws {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-claude-org-app")
settings.addTokenAccount(
provider: .claude,
label: "Team",
token: "sk-ant-session-token",
organizationID: " org-team ")
let snapshot = ProviderRegistry.makeSettingsSnapshot(settings: settings, tokenOverride: nil)
let claudeSettings = try #require(snapshot.claude)
#expect(claudeSettings.manualCookieHeader == "sessionKey=sk-ant-session-token")
#expect(claudeSettings.organizationID == "org-team")
}
@Test
func `claude OAuth token selection forces OAuth in CLI settings snapshot`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "Bearer sk-ant-oat-account-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
cookieSource: .auto,
tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .claude).first)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: account))
let claudeSettings = try #require(snapshot.claude)
#expect(claudeSettings.usageDataSource == .oauth)
#expect(claudeSettings.cookieSource == .off)
#expect(claudeSettings.manualCookieHeader == nil)
}
@Test
func `claude OAuth token selection injects environment override in CLI`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "Bearer sk-ant-oat-account-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(id: .claude, tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .claude).first)
let env = tokenContext.environment(base: ["FOO": "bar"], provider: .claude, account: account)
#expect(env["FOO"] == "bar")
#expect(env[ClaudeOAuthCredentialsStore.environmentTokenKey] == "sk-ant-oat-account-token")
}
@Test
func `claude session account strips ambient admin api credentials in CLI environment builder`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "sk-ant-session-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
apiKey: "sk-ant-admin-config",
tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .claude).first)
let env = tokenContext.environment(
base: [
"FOO": "bar",
ClaudeAdminAPISettingsReader.alternateAdminAPIKeyEnvironmentKey: "sk-ant-admin-base",
ClaudeOAuthCredentialsStore.environmentTokenKey: "sk-ant-oat-base",
],
provider: .claude,
account: account)
#expect(env["FOO"] == "bar")
#expect(env[ClaudeAdminAPISettingsReader.adminAPIKeyEnvironmentKey] == nil)
#expect(env[ClaudeAdminAPISettingsReader.alternateAdminAPIKeyEnvironmentKey] == nil)
#expect(env[ClaudeOAuthCredentialsStore.environmentTokenKey] == nil)
}
@Test
func `claude OAuth token selection promotes auto source mode in CLI`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "Bearer sk-ant-oat-account-token",
addedAt: 0,
lastUsed: nil)
let config = CodexBarConfig(providers: [ProviderConfig(id: .claude)])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false)
let effectiveSourceMode = tokenContext.effectiveSourceMode(
base: .auto,
provider: .claude,
account: account)
#expect(effectiveSourceMode == .oauth)
}
@Test
func `claude OAuth token selection reroutes explicit CLI source to OAuth in CLI`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "Bearer sk-ant-oat-account-token",
addedAt: 0,
lastUsed: nil)
let config = CodexBarConfig(providers: [ProviderConfig(id: .claude)])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false)
let effectiveSourceMode = tokenContext.effectiveSourceMode(
base: .cli,
provider: .claude,
account: account)
#expect(effectiveSourceMode == .oauth)
}
@Test
func `claude session key selection reroutes explicit CLI source to Web in CLI`() throws {
let account = ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "sk-ant-session-token",
addedAt: 0,
lastUsed: nil)
let config = CodexBarConfig(providers: [ProviderConfig(id: .claude)])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false)
let effectiveSourceMode = tokenContext.effectiveSourceMode(
base: .cli,
provider: .claude,
account: account)
#expect(effectiveSourceMode == .web)
}
@Test
func `claude all accounts reroutes explicit CLI source per selected credential in CLI`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "OAuth",
token: "Bearer sk-ant-oat-account-token",
addedAt: 0,
lastUsed: nil),
ProviderTokenAccount(
id: UUID(),
label: "Session",
token: "sk-ant-session-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(id: .claude, tokenAccounts: accounts),
])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: true),
config: config,
verbose: false)
let resolved = try tokenContext.resolvedAccounts(for: .claude)
#expect(resolved.map(\.label) == ["OAuth", "Session"])
let oauth = try #require(resolved.first)
let oauthSnapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: oauth)?.claude)
#expect(tokenContext.effectiveSourceMode(base: .cli, provider: .claude, account: oauth) == .oauth)
#expect(oauthSnapshot.usageDataSource == .oauth)
#expect(tokenContext.environment(base: [:], provider: .claude, account: oauth)[
ClaudeOAuthCredentialsStore.environmentTokenKey,
] == "sk-ant-oat-account-token")
let session = try #require(resolved.dropFirst().first)
let sessionSnapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: session)?.claude)
#expect(tokenContext.effectiveSourceMode(base: .cli, provider: .claude, account: session) == .web)
#expect(sessionSnapshot.cookieSource == .manual)
#expect(sessionSnapshot.manualCookieHeader == "sessionKey=sk-ant-session-token")
}
@Test
func `codex all accounts selection exposes configured accounts and scopes CLI homes`() throws {
let root = FileManager.default.temporaryDirectory
.appendingPathComponent("codex-cli-all-accounts-\(UUID().uuidString)", isDirectory: true)
let ambientHome = root.appendingPathComponent("ambient", isDirectory: true)
let firstHome = root.appendingPathComponent("first", isDirectory: true)
let secondHome = root.appendingPathComponent("second", isDirectory: true)
let profileHome = root.appendingPathComponent("profile", isDirectory: true)
defer { try? FileManager.default.removeItem(at: root) }
try FileManager.default.createDirectory(at: ambientHome, withIntermediateDirectories: true)
try FileManager.default.createDirectory(at: firstHome, withIntermediateDirectories: true)
try FileManager.default.createDirectory(at: secondHome, withIntermediateDirectories: true)
try Self.writeCodexAuthFile(
homeURL: profileHome,
email: "profile@example.com",
accountID: "acct_profile")
let storeURL = root.appendingPathComponent("managed-codex-accounts.json")
let firstID = UUID()
let secondID = UUID()
let accounts = ManagedCodexAccountSet(version: FileManagedCodexAccountStore.currentVersion, accounts: [
ManagedCodexAccount(
id: firstID,
email: "FIRST@EXAMPLE.COM",
workspaceLabel: "Team",
managedHomePath: firstHome.path,
createdAt: 0,
updatedAt: 0,
lastAuthenticatedAt: nil),
ManagedCodexAccount(
id: secondID,
email: "second@example.com",
workspaceLabel: "Personal",
managedHomePath: secondHome.path,
createdAt: 0,
updatedAt: 0,
lastAuthenticatedAt: nil),
])
try FileManagedCodexAccountStore(fileURL: storeURL).storeAccounts(accounts)
let config = CodexBarConfig(providers: [
ProviderConfig(
id: .codex,
codexActiveSource: .managedAccount(id: secondID),
codexProfileHomePaths: [profileHome.path]),
])
let context = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: true),
config: config,
verbose: false,
baseEnvironment: ["CODEX_HOME": ambientHome.path],
managedCodexAccountStoreURL: storeURL)
let projection = context.visibleCodexAccounts()
#expect(projection.visibleAccounts.map(\.menuDisplayName) == [
"first@example.com — Team",
"profile@example.com",
"second@example.com",
])
#expect(projection.visibleAccounts.map(\.selectionSource) == [
.managedAccount(id: firstID),
.profileHome(path: profileHome.path),
.managedAccount(id: secondID),
])
#expect(projection.visibleAccounts.first { $0.email == "second@example.com" }?.isActive == true)
let firstEnv = context.environment(
base: ["CODEX_HOME": ambientHome.path],
provider: .codex,
account: nil,
codexActiveSourceOverride: .managedAccount(id: firstID))
#expect(firstEnv["CODEX_HOME"] == firstHome.path)
let profileEnv = context.environment(
base: ["CODEX_HOME": ambientHome.path],
provider: .codex,
account: nil,
codexActiveSourceOverride: .profileHome(path: profileHome.path))
#expect(profileEnv["CODEX_HOME"] == profileHome.path)
#expect(context.settingsSnapshot(
for: .codex,
account: nil,
codexActiveSourceOverride: .profileHome(path: profileHome.path))?.codex?.openAIWebCacheScope
== .profileHome(profileHome.path))
let liveEnv = context.environment(
base: ["CODEX_HOME": ambientHome.path],
provider: .codex,
account: nil,
codexActiveSourceOverride: .liveSystem)
#expect(liveEnv["CODEX_HOME"] == ambientHome.path)
let firstFetcher = context.fetcher(
base: UsageFetcher(environment: ["CODEX_HOME": ambientHome.path]),
provider: .codex,
env: firstEnv)
#expect(Self.codexHomePath(from: firstFetcher) == firstHome.path)
let nonCodexBaseFetcher = UsageFetcher(environment: ["CODEX_HOME": ambientHome.path])
let nonCodexFetcher = context.fetcher(base: nonCodexBaseFetcher, provider: .claude, env: firstEnv)
#expect(Self.codexHomePath(from: nonCodexFetcher) == ambientHome.path)
let labeled = try context.applyCodexVisibleAccountLabel(
UsageSnapshot(primary: nil, secondary: nil, updatedAt: Date()),
account: #require(projection.visibleAccounts.first))
let identity = try #require(labeled.identity(for: .codex))
#expect(identity.accountEmail == "first@example.com")
#expect(identity.accountOrganization == "Team")
}
@Test
func `codex CLI ignores relative profile homes`() throws {
let config = CodexBarConfig(providers: [
ProviderConfig(
id: .codex,
codexActiveSource: .profileHome(path: "relative-codex-home"),
codexProfileHomePaths: ["relative-codex-home"]),
])
let context = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false,
baseEnvironment: ["CODEX_HOME": "/tmp/ambient-codex"])
let environment = context.environment(
base: ["CODEX_HOME": "/tmp/ambient-codex"],
provider: .codex,
account: nil,
codexActiveSourceOverride: .profileHome(path: "relative-codex-home"))
#expect(context.visibleCodexAccounts().visibleAccounts.isEmpty)
#expect(environment["CODEX_HOME"] == "/tmp/ambient-codex")
}
@Test
func `claude ambient explicit CLI source remains CLI in CLI`() throws {
let config = CodexBarConfig(providers: [ProviderConfig(id: .claude)])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false)
let effectiveSourceMode = tokenContext.effectiveSourceMode(
base: .cli,
provider: .claude,
account: nil)
#expect(effectiveSourceMode == .cli)
}
@Test
func `claude session key selection stays in manual cookie mode in CLI settings snapshot`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Primary",
token: "sk-ant-session-token",
addedAt: 0,
lastUsed: nil),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
cookieSource: .auto,
tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .claude).first)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: account))
let claudeSettings = try #require(snapshot.claude)
#expect(claudeSettings.usageDataSource == .auto)
#expect(claudeSettings.cookieSource == .manual)
#expect(claudeSettings.manualCookieHeader == "sessionKey=sk-ant-session-token")
}
@Test
func `claude session key selection carries organization id in CLI settings snapshot`() throws {
let accounts = ProviderTokenAccountData(
version: 1,
accounts: [
ProviderTokenAccount(
id: UUID(),
label: "Team",
token: "sk-ant-session-token",
addedAt: 0,
lastUsed: nil,
organizationID: " org-team "),
],
activeIndex: 0)
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
tokenAccounts: accounts),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let account = try #require(tokenContext.resolvedAccounts(for: .claude).first)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: account))
let claudeSettings = try #require(snapshot.claude)
#expect(claudeSettings.organizationID == "org-team")
}
@Test
func `claude token account organization id uses organizationId JSON key`() throws {
let json = """
{
"id": "00000000-0000-0000-0000-000000000001",
"label": "Team",
"token": "sk-ant-session-token",
"addedAt": 0,
"lastUsed": null,
"organizationId": "org-team"
}
"""
let account = try JSONDecoder().decode(ProviderTokenAccount.self, from: Data(json.utf8))
let encoded = try JSONSerialization.jsonObject(with: JSONEncoder().encode(account)) as? [String: Any]
#expect(account.organizationID == "org-team")
#expect(encoded?["organizationId"] as? String == "org-team")
#expect(encoded?["organizationID"] == nil)
}
@Test
func `claude config manual cookie uses shared route in CLI settings snapshot`() throws {
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
cookieHeader: "Cookie: sessionKey=sk-ant-session-token; foo=bar"),
])
let selection = TokenAccountCLISelection(label: nil, index: nil, allAccounts: false)
let tokenContext = try TokenAccountCLIContext(selection: selection, config: config, verbose: false)
let snapshot = try #require(tokenContext.settingsSnapshot(for: .claude, account: nil))
let claudeSettings = try #require(snapshot.claude)
#expect(claudeSettings.usageDataSource == .auto)
#expect(claudeSettings.cookieSource == .manual)
#expect(claudeSettings.manualCookieHeader == "sessionKey=sk-ant-session-token; foo=bar")
}
@Test
func `claude config manual cookie does not promote auto source mode in CLI`() throws {
let config = CodexBarConfig(
providers: [
ProviderConfig(
id: .claude,
cookieHeader: "Cookie: sessionKey=sk-ant-session-token"),
])
let tokenContext = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: config,
verbose: false)
let effectiveSourceMode = tokenContext.effectiveSourceMode(
base: .auto,
provider: .claude,
account: nil)
#expect(effectiveSourceMode == .auto)
}
@Test
func `apply account label in app preserves snapshot fields`() {
let settings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-apply-app")
let store = Self.makeUsageStore(settings: settings)
let snapshot = Self.makeSnapshotWithAllFields(provider: .zai)
let account = ProviderTokenAccount(
id: UUID(),
label: "Team Account",
token: "account-token",
addedAt: 0,
lastUsed: nil)
let labeled = store.applyAccountLabel(snapshot, provider: .zai, account: account)
Self.expectSnapshotFieldsPreserved(before: snapshot, after: labeled)
#expect(labeled.identity?.providerID == .zai)
#expect(labeled.identity?.accountEmail == "Team Account")
}
@Test
func `apply account label in CLI preserves snapshot fields`() throws {
let context = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: CodexBarConfig(providers: []),
verbose: false)
let snapshot = Self.makeSnapshotWithAllFields(provider: .zai)
let account = ProviderTokenAccount(
id: UUID(),
label: "CLI Account",
token: "account-token",
addedAt: 0,
lastUsed: nil)
let labeled = context.applyAccountLabel(snapshot, provider: .zai, account: account)
Self.expectSnapshotFieldsPreserved(before: snapshot, after: labeled)
#expect(labeled.identity?.providerID == .zai)
#expect(labeled.identity?.accountEmail == "CLI Account")
}
@Test
func `codex known owners match between app and CLI for live system only`() throws {
let ambientHome = Self.makeTempCodexHome(
email: "live@example.com",
plan: "pro",
accountId: "acct-live")
defer { try? FileManager.default.removeItem(at: ambientHome) }
let appSettings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-codex-live-only")
appSettings._test_liveSystemCodexAccount = ObservedSystemCodexAccount(
email: "live@example.com",
codexHomePath: ambientHome.path,
observedAt: Date(),
identity: .providerAccount(id: "acct-live"))
defer { appSettings._test_liveSystemCodexAccount = nil }
let appStore = Self.makeUsageStore(settings: appSettings)
try Self.withCLIKnownOwnerFixtures(
ambientHome: ambientHome,
managedAccounts: [])
{ managedStoreURL in
let rawCLIOwners = try Self.codexCLIKnownOwners(
ambientHome: ambientHome,
managedStoreURL: managedStoreURL)
let cliOwners = try #require(rawCLIOwners)
let appOwners = appStore.codexDashboardKnownOwnerCandidates()
#expect(Self.knownOwnerMultiset(appOwners) == Self.knownOwnerMultiset(cliOwners))
}
}
@Test
func `codex known owners match between app and CLI when managed and live identities are the same`() throws {
let ambientHome = Self.makeTempCodexHome(
email: "shared@example.com",
plan: "pro",
accountId: "acct-shared")
let managedHome = Self.makeTempCodexHome(
email: "shared@example.com",
plan: "pro",
accountId: "acct-shared")
defer {
try? FileManager.default.removeItem(at: ambientHome)
try? FileManager.default.removeItem(at: managedHome)
}
let managedAccount = ManagedCodexAccount(
id: UUID(),
email: "shared@example.com",
managedHomePath: managedHome.path,
createdAt: 1,
updatedAt: 2,
lastAuthenticatedAt: 3)
let appSettings = Self.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-codex-same-identity")
appSettings._test_activeManagedCodexAccount = managedAccount
appSettings._test_liveSystemCodexAccount = ObservedSystemCodexAccount(
email: "shared@example.com",
codexHomePath: ambientHome.path,
observedAt: Date(),
identity: .providerAccount(id: "acct-shared"))
defer {
appSettings._test_activeManagedCodexAccount = nil
appSettings._test_liveSystemCodexAccount = nil
}
let appStore = Self.makeUsageStore(settings: appSettings)
try Self.withCLIKnownOwnerFixtures(
ambientHome: ambientHome,
managedAccounts: [managedAccount])
{ managedStoreURL in
let rawCLIOwners = try Self.codexCLIKnownOwners(
ambientHome: ambientHome,
managedStoreURL: managedStoreURL)
let cliOwners = try #require(rawCLIOwners)
let appOwners = appStore.codexDashboardKnownOwnerCandidates()
#expect(Self.knownOwnerMultiset(appOwners) == Self.knownOwnerMultiset(cliOwners))
}
}
@Test
func `codex known owners match between app and CLI when managed and live identities differ`() throws {
let ambientHome = Self.makeTempCodexHome(
email: "live@example.com",
plan: "pro",
accountId: "acct-live")
let managedHome = Self.makeTempCodexHome(
email: "managed@example.com",
plan: "pro",
accountId: "acct-managed")
defer {
try? FileManager.default.removeItem(at: ambientHome)
try? FileManager.default.removeItem(at: managedHome)
}
let managedAccount = ManagedCodexAccount(
id: UUID(),
email: "managed@example.com",
managedHomePath: managedHome.path,
createdAt: 1,
updatedAt: 2,
lastAuthenticatedAt: 3)
let appSettings = Self
.makeSettingsStore(suite: "TokenAccountEnvironmentPrecedenceTests-codex-different-identities")
appSettings._test_activeManagedCodexAccount = managedAccount
appSettings._test_liveSystemCodexAccount = ObservedSystemCodexAccount(
email: "live@example.com",
codexHomePath: ambientHome.path,
observedAt: Date(),
identity: .providerAccount(id: "acct-live"))
defer {
appSettings._test_activeManagedCodexAccount = nil
appSettings._test_liveSystemCodexAccount = nil
}
let appStore = Self.makeUsageStore(settings: appSettings)
try Self.withCLIKnownOwnerFixtures(
ambientHome: ambientHome,
managedAccounts: [managedAccount])
{ managedStoreURL in
let rawCLIOwners = try Self.codexCLIKnownOwners(
ambientHome: ambientHome,
managedStoreURL: managedStoreURL)
let cliOwners = try #require(rawCLIOwners)
let appOwners = appStore.codexDashboardKnownOwnerCandidates()
#expect(Self.knownOwnerMultiset(appOwners) == Self.knownOwnerMultiset(cliOwners))
}
}
}
extension TokenAccountEnvironmentPrecedenceTests {
fileprivate static func makeSettingsStore(suite: String) -> SettingsStore {
let defaults = UserDefaults(suiteName: suite)!
defaults.removePersistentDomain(forName: suite)
let configStore = testConfigStore(suiteName: suite)
return SettingsStore(
userDefaults: defaults,
configStore: configStore,
zaiTokenStore: NoopZaiTokenStore(),
syntheticTokenStore: NoopSyntheticTokenStore(),
codexCookieStore: InMemoryCookieHeaderStore(),
claudeCookieStore: InMemoryCookieHeaderStore(),
cursorCookieStore: InMemoryCookieHeaderStore(),
opencodeCookieStore: InMemoryCookieHeaderStore(),
factoryCookieStore: InMemoryCookieHeaderStore(),
minimaxCookieStore: InMemoryMiniMaxCookieStore(),
minimaxAPITokenStore: InMemoryMiniMaxAPITokenStore(),
kimiTokenStore: InMemoryKimiTokenStore(),
kimiK2TokenStore: InMemoryKimiK2TokenStore(),
augmentCookieStore: InMemoryCookieHeaderStore(),
ampCookieStore: InMemoryCookieHeaderStore(),
copilotTokenStore: InMemoryCopilotTokenStore(),
tokenAccountStore: InMemoryTokenAccountStore())
}
fileprivate static func makeUsageStore(settings: SettingsStore) -> UsageStore {
UsageStore(
fetcher: UsageFetcher(environment: [:]),
browserDetection: BrowserDetection(cacheTTL: 0),
settings: settings)
}
fileprivate static func codexCLIKnownOwners(
ambientHome: URL,
managedStoreURL: URL) throws -> [CodexDashboardKnownOwnerCandidate]?
{
let context = try TokenAccountCLIContext(
selection: TokenAccountCLISelection(label: nil, index: nil, allAccounts: false),
config: CodexBarConfig(providers: [ProviderConfig(id: .codex)]),
verbose: false,
baseEnvironment: ["CODEX_HOME": ambientHome.path],
managedCodexAccountStoreURL: managedStoreURL)
return context.settingsSnapshot(for: .codex, account: nil)?.codex?.dashboardAuthorityKnownOwners
}
fileprivate static func codexHomePath(from fetcher: UsageFetcher) -> String? {
guard let environment = Mirror(reflecting: fetcher).children.first(where: { $0.label == "environment" })?
.value as? [String: String]
else {
return nil
}
return environment["CODEX_HOME"]
}
fileprivate static func writeCodexAuthFile(homeURL: URL, email: String, accountID: String) throws {
try FileManager.default.createDirectory(at: homeURL, withIntermediateDirectories: true)
let auth: [String: Any] = [
"tokens": [
"accessToken": "access-token",
"refreshToken": "refresh-token",
"idToken": self.fakeJWT(email: email, plan: "pro", accountId: accountID),
"account_id": accountID,
],
]
let data = try JSONSerialization.data(withJSONObject: auth)
try data.write(to: homeURL.appendingPathComponent("auth.json"))
}
fileprivate static func knownOwnerMultiset(
_ owners: [CodexDashboardKnownOwnerCandidate]) -> [CodexDashboardKnownOwnerCandidate: Int]
{
owners.reduce(into: [:]) { counts, owner in
counts[owner, default: 0] += 1
}
}
fileprivate static func makeTempCodexHome(email: String, plan: String, accountId: String) -> URL {
let home = FileManager.default.temporaryDirectory
.appendingPathComponent("codex-known-owner-\(UUID().uuidString)", isDirectory: true)
try? FileManager.default.createDirectory(at: home, withIntermediateDirectories: true)
let credentials = CodexOAuthCredentials(
accessToken: "access-token",
refreshToken: "refresh-token",
idToken: self.fakeJWT(email: email, plan: plan, accountId: accountId),
accountId: accountId,
lastRefresh: Date())
try? CodexOAuthCredentialsStore.save(credentials, env: ["CODEX_HOME": home.path])
return home
}
fileprivate static func fakeJWT(email: String, plan: String, accountId: String) -> String {
let header = (try? JSONSerialization.data(withJSONObject: ["alg": "none"])) ?? Data()
let payload = (try? JSONSerialization.data(withJSONObject: [
"email": email,
"chatgpt_plan_type": plan,
"https://api.openai.com/auth": [
"chatgpt_plan_type": plan,
"chatgpt_account_id": accountId,
],
])) ?? Data()
func base64URL(_ data: Data) -> String {
data.base64EncodedString()
.replacingOccurrences(of: "=", with: "")
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
}
return "\(base64URL(header)).\(base64URL(payload))."
}
fileprivate static func withCLIKnownOwnerFixtures<T>(
ambientHome: URL,
managedAccounts: [ManagedCodexAccount],
operation: (URL) throws -> T) throws -> T
{
let root = FileManager.default.temporaryDirectory
.appendingPathComponent("codex-known-owner-store-\(UUID().uuidString)", isDirectory: true)
let managedStoreURL = root.appendingPathComponent("managed-codex-accounts.json", isDirectory: false)
let fileManager = FileManager.default
defer { try? fileManager.removeItem(at: root) }
let managedStore = FileManagedCodexAccountStore(fileURL: managedStoreURL)
try managedStore.storeAccounts(ManagedCodexAccountSet(
version: FileManagedCodexAccountStore.currentVersion,
accounts: managedAccounts))
return try operation(managedStoreURL)
}
fileprivate static func makeSnapshotWithAllFields(provider: UsageProvider) -> UsageSnapshot {
let now = Date(timeIntervalSince1970: 1_700_000_000)
let reset = Date(timeIntervalSince1970: 1_700_003_600)
let tokenLimit = ZaiLimitEntry(
type: .tokensLimit,
unit: .hours,
number: 6,
usage: 200,
currentValue: 40,
remaining: 160,
percentage: 20,
usageDetails: [ZaiUsageDetail(modelCode: "glm-4", usage: 40)],
nextResetTime: reset)
let identity = ProviderIdentitySnapshot(
providerID: provider,
accountEmail: nil,
accountOrganization: "Org",
loginMethod: "Pro")
return UsageSnapshot(
primary: RateWindow(usedPercent: 21, windowMinutes: 60, resetsAt: reset, resetDescription: "primary"),
secondary: RateWindow(usedPercent: 42, windowMinutes: 1440, resetsAt: nil, resetDescription: "secondary"),
tertiary: RateWindow(usedPercent: 7, windowMinutes: nil, resetsAt: nil, resetDescription: "tertiary"),
providerCost: ProviderCostSnapshot(
used: 12.5,
limit: 25,
currencyCode: "USD",
period: "Monthly",
resetsAt: reset,
updatedAt: now),
zaiUsage: ZaiUsageSnapshot(
tokenLimit: tokenLimit,
timeLimit: nil,
planName: "Z.ai Pro",
updatedAt: now),
minimaxUsage: MiniMaxUsageSnapshot(
planName: "MiniMax",
availablePrompts: 500,
currentPrompts: 120,
remainingPrompts: 380,
windowMinutes: 1440,
usedPercent: 24,
resetsAt: reset,
updatedAt: now),
openRouterUsage: OpenRouterUsageSnapshot(
totalCredits: 50,
totalUsage: 10,
balance: 40,
usedPercent: 20,
rateLimit: nil,
updatedAt: now),
cursorRequests: CursorRequestUsage(used: 7, limit: 70),
subscriptionExpiresAt: reset.addingTimeInterval(86400),
subscriptionRenewsAt: reset.addingTimeInterval(43200),
updatedAt: now,
identity: identity)
}
fileprivate static func expectSnapshotFieldsPreserved(before: UsageSnapshot, after: UsageSnapshot) {
#expect(after.primary?.usedPercent == before.primary?.usedPercent)
#expect(after.secondary?.usedPercent == before.secondary?.usedPercent)
#expect(after.tertiary?.usedPercent == before.tertiary?.usedPercent)
#expect(after.providerCost?.used == before.providerCost?.used)
#expect(after.providerCost?.limit == before.providerCost?.limit)
#expect(after.providerCost?.currencyCode == before.providerCost?.currencyCode)
#expect(after.zaiUsage?.planName == before.zaiUsage?.planName)
#expect(after.zaiUsage?.tokenLimit?.usage == before.zaiUsage?.tokenLimit?.usage)
#expect(after.minimaxUsage?.planName == before.minimaxUsage?.planName)
#expect(after.minimaxUsage?.availablePrompts == before.minimaxUsage?.availablePrompts)
#expect(after.openRouterUsage?.balance == before.openRouterUsage?.balance)
#expect(after.openRouterUsage?.rateLimit?.requests == before.openRouterUsage?.rateLimit?.requests)
#expect(after.cursorRequests?.used == before.cursorRequests?.used)
#expect(after.cursorRequests?.limit == before.cursorRequests?.limit)
#expect(after.subscriptionExpiresAt == before.subscriptionExpiresAt)
#expect(after.subscriptionRenewsAt == before.subscriptionRenewsAt)
#expect(after.updatedAt == before.updatedAt)
}
}