import Foundationimport Testing@testable import CodexBarCore @Suite(.serialized)struct CookieHeaderCacheTests { private struct WrongEntry: Codable { let value: String } @Test func `stores and loads entry`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) CookieHeaderCache.store( provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome", now: storedAt) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=abc") #expect(loaded?.sourceLabel == "Chrome") #expect(loaded?.storedAt == storedAt) } @Test func `stores separate codex entries per managed account scope`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountA), cookieHeader: "auth=account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountB), cookieHeader: "auth=account-b", sourceLabel: "Safari") defer { CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountA)) CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountB)) } #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountA))? .cookieHeader == "auth=account-a") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountB))? .cookieHeader == "auth=account-b") #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == nil) } @Test func `profile home scopes isolate same email sessions without exposing paths`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let profileA = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-a") let profileB = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-b") CookieHeaderCache.store( provider: provider, scope: profileA, cookieHeader: "auth=profile-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: profileB, cookieHeader: "auth=profile-b", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider, scope: profileA) CookieHeaderCache.clear(provider: provider, scope: profileB) } #expect(CookieHeaderCache.load(provider: provider, scope: profileA)?.cookieHeader == "auth=profile-a") #expect(CookieHeaderCache.load(provider: provider, scope: profileB)?.cookieHeader == "auth=profile-b") #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(profileA.isolationIdentifier != profileB.isolationIdentifier) #expect(!profileA.isolationIdentifier.contains("codex-profile-a")) } @Test func `provider global scope remains available without managed account`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex CookieHeaderCache.store( provider: provider, cookieHeader: "auth=system", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider) } #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=system") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(UUID())) == nil) } @Test func `claude cookie scopes isolate browser cache from managed accounts`() { self.withIsolatedCookieCache { let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-browser", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountA), cookieHeader: "sessionKey=sk-ant-account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountB), cookieHeader: "sessionKey=sk-ant-account-b", sourceLabel: "Edge") #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-browser") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountA)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA)) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") } } @Test func `claude unreadable managed store sentinel is isolated from account cookies`() { self.withIsolatedCookieCache { let accountID = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountID), cookieHeader: "sessionKey=sk-ant-account", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedStoreUnreadable, cookieHeader: "sessionKey=sk-ant-unreadable-store", sourceLabel: "Unreadable managed account store") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountID)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountID)) == nil) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-global") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 1, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable) == nil) } } @Test func `claude clear all scopes does not remove other provider cookie caches`() { self.withIsolatedCookieCache { let claudeAccount = UUID() let codexAccount = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-claude-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(claudeAccount), cookieHeader: "sessionKey=sk-ant-claude-account", sourceLabel: "Chrome") CookieHeaderCache.store(provider: .codex, cookieHeader: "auth=codex-global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .codex, scope: .managedAccount(codexAccount), cookieHeader: "auth=codex-account", sourceLabel: "Safari") CookieHeaderCache.store(provider: .perplexity, cookieHeader: "pplx=web", sourceLabel: "Chrome") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 2, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(claudeAccount)) == nil) #expect(CookieHeaderCache.load(provider: .codex)?.cookieHeader == "auth=codex-global") #expect(CookieHeaderCache.load(provider: .codex, scope: .managedAccount(codexAccount))? .cookieHeader == "auth=codex-account") #expect(CookieHeaderCache.load(provider: .perplexity)?.cookieHeader == "pplx=web") } } @Test func `migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) let entry = CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: storedAt, sourceLabel: "Legacy") let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store(entry, to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(loaded?.sourceLabel == "Legacy") #expect(loaded?.storedAt == storedAt) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) let loadedAgain = CookieHeaderCache.load(provider: provider) #expect(loadedAgain?.cookieHeader == "auth=legacy") } @Test func `serialized load migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) let loaded = CookieHeaderCache.loadSerialized(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=legacy") } #if os(macOS) @Test func `temporary keychain unavailability returns nil without migrating legacy file`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = KeychainCacheStore.withLoadFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.load(provider: provider) } #expect(loaded == nil) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) switch KeychainCacheStore.load(key: .cookie(provider: provider), as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected temporary miss not to migrate legacy cache") } } #endif @Test func `invalid keychain cache is cleared`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let key = KeychainCacheStore.Key.cookie(provider: provider) KeychainCacheStore.store(key: key, entry: WrongEntry(value: "not-a-cookie-entry")) #expect(CookieHeaderCache.load(provider: provider) == nil) switch KeychainCacheStore.load(key: key, as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected invalid cookie cache to be cleared") } } @Test func `clear all scopes removes global scoped invalid and legacy cookie entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let accountID = UUID() CookieHeaderCache.store(provider: provider, cookieHeader: "auth=global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountID), cookieHeader: "auth=scoped", sourceLabel: "Chrome") KeychainCacheStore.store( key: .cookie(provider: provider, scopeIdentifier: "managed-store-unreadable"), entry: WrongEntry(value: "invalid")) CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: provider) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 4, failedCount: 0)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedAccount(accountID))) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedStoreUnreadable)) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) } @Test func `loadForDisplay memoizes keychain lookups`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") // Remove the backing entry without going through CookieHeaderCache: the strict load // sees the change, the display path keeps serving the memoized snapshot. KeychainCacheStore.clear(key: .cookie(provider: provider)) #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") } @Test func `loadForDisplay memoizes missing entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=behind-the-back", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) defer { KeychainCacheStore.clear(key: .cookie(provider: provider)) } #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `loadForDisplay migrates legacy cache asynchronously`() async throws { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=legacy-display") for _ in 0..<500 { if !CookieHeaderCache.hasLegacyEntryForTesting(provider: provider), CookieHeaderCache.hasKeychainEntryForTesting(provider: provider) { break } try await Task.sleep(for: .milliseconds(10)) } #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) } @Test func `delayed legacy migration cannot restore a cleared cache`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) #expect(CookieHeaderCache.migrateLegacyEntryIfNeededForTesting(provider: provider) == nil) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) } @Test func `legacy URL override supports concurrent teardown reads`() { let legacyBases = [ FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), ] defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } DispatchQueue.concurrentPerform(iterations: 5000) { index in if index.isMultiple(of: 3) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[index % legacyBases.count]) } else if index.isMultiple(of: 5) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } else { _ = CookieHeaderCache.legacyURLForTesting(provider: .codex) } } CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[0]) #expect( CookieHeaderCache.legacyURLForTesting(provider: .codex)Lines 1–500 of 847. Load more
import Foundation import Testing @testable import CodexBarCore @Suite(.serialized) struct CookieHeaderCacheTests { private struct WrongEntry: Codable { let value: String } @Test func `stores and loads entry`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) CookieHeaderCache.store( provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome", now: storedAt) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=abc") #expect(loaded?.sourceLabel == "Chrome") #expect(loaded?.storedAt == storedAt) } @Test func `stores separate codex entries per managed account scope`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountA), cookieHeader: "auth=account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountB), cookieHeader: "auth=account-b", sourceLabel: "Safari") defer { CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountA)) CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountB)) } #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountA))? .cookieHeader == "auth=account-a") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountB))? .cookieHeader == "auth=account-b") #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == nil) } @Test func `profile home scopes isolate same email sessions without exposing paths`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let profileA = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-a") let profileB = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-b") CookieHeaderCache.store( provider: provider, scope: profileA, cookieHeader: "auth=profile-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: profileB, cookieHeader: "auth=profile-b", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider, scope: profileA) CookieHeaderCache.clear(provider: provider, scope: profileB) } #expect(CookieHeaderCache.load(provider: provider, scope: profileA)?.cookieHeader == "auth=profile-a") #expect(CookieHeaderCache.load(provider: provider, scope: profileB)?.cookieHeader == "auth=profile-b") #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(profileA.isolationIdentifier != profileB.isolationIdentifier) #expect(!profileA.isolationIdentifier.contains("codex-profile-a")) } @Test func `provider global scope remains available without managed account`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex CookieHeaderCache.store( provider: provider, cookieHeader: "auth=system", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider) } #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=system") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(UUID())) == nil) } @Test func `claude cookie scopes isolate browser cache from managed accounts`() { self.withIsolatedCookieCache { let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-browser", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountA), cookieHeader: "sessionKey=sk-ant-account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountB), cookieHeader: "sessionKey=sk-ant-account-b", sourceLabel: "Edge") #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-browser") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountA)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA)) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") } } @Test func `claude unreadable managed store sentinel is isolated from account cookies`() { self.withIsolatedCookieCache { let accountID = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountID), cookieHeader: "sessionKey=sk-ant-account", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedStoreUnreadable, cookieHeader: "sessionKey=sk-ant-unreadable-store", sourceLabel: "Unreadable managed account store") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountID)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountID)) == nil) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-global") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 1, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable) == nil) } } @Test func `claude clear all scopes does not remove other provider cookie caches`() { self.withIsolatedCookieCache { let claudeAccount = UUID() let codexAccount = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-claude-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(claudeAccount), cookieHeader: "sessionKey=sk-ant-claude-account", sourceLabel: "Chrome") CookieHeaderCache.store(provider: .codex, cookieHeader: "auth=codex-global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .codex, scope: .managedAccount(codexAccount), cookieHeader: "auth=codex-account", sourceLabel: "Safari") CookieHeaderCache.store(provider: .perplexity, cookieHeader: "pplx=web", sourceLabel: "Chrome") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 2, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(claudeAccount)) == nil) #expect(CookieHeaderCache.load(provider: .codex)?.cookieHeader == "auth=codex-global") #expect(CookieHeaderCache.load(provider: .codex, scope: .managedAccount(codexAccount))? .cookieHeader == "auth=codex-account") #expect(CookieHeaderCache.load(provider: .perplexity)?.cookieHeader == "pplx=web") } } @Test func `migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) let entry = CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: storedAt, sourceLabel: "Legacy") let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store(entry, to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(loaded?.sourceLabel == "Legacy") #expect(loaded?.storedAt == storedAt) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) let loadedAgain = CookieHeaderCache.load(provider: provider) #expect(loadedAgain?.cookieHeader == "auth=legacy") } @Test func `serialized load migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) let loaded = CookieHeaderCache.loadSerialized(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=legacy") } #if os(macOS) @Test func `temporary keychain unavailability returns nil without migrating legacy file`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = KeychainCacheStore.withLoadFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.load(provider: provider) } #expect(loaded == nil) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) switch KeychainCacheStore.load(key: .cookie(provider: provider), as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected temporary miss not to migrate legacy cache") } } #endif @Test func `invalid keychain cache is cleared`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let key = KeychainCacheStore.Key.cookie(provider: provider) KeychainCacheStore.store(key: key, entry: WrongEntry(value: "not-a-cookie-entry")) #expect(CookieHeaderCache.load(provider: provider) == nil) switch KeychainCacheStore.load(key: key, as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected invalid cookie cache to be cleared") } } @Test func `clear all scopes removes global scoped invalid and legacy cookie entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let accountID = UUID() CookieHeaderCache.store(provider: provider, cookieHeader: "auth=global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountID), cookieHeader: "auth=scoped", sourceLabel: "Chrome") KeychainCacheStore.store( key: .cookie(provider: provider, scopeIdentifier: "managed-store-unreadable"), entry: WrongEntry(value: "invalid")) CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: provider) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 4, failedCount: 0)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedAccount(accountID))) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedStoreUnreadable)) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) } @Test func `loadForDisplay memoizes keychain lookups`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") // Remove the backing entry without going through CookieHeaderCache: the strict load // sees the change, the display path keeps serving the memoized snapshot. KeychainCacheStore.clear(key: .cookie(provider: provider)) #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") } @Test func `loadForDisplay memoizes missing entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=behind-the-back", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) defer { KeychainCacheStore.clear(key: .cookie(provider: provider)) } #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `loadForDisplay migrates legacy cache asynchronously`() async throws { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=legacy-display") for _ in 0..<500 { if !CookieHeaderCache.hasLegacyEntryForTesting(provider: provider), CookieHeaderCache.hasKeychainEntryForTesting(provider: provider) { break } try await Task.sleep(for: .milliseconds(10)) } #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) } @Test func `delayed legacy migration cannot restore a cleared cache`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) #expect(CookieHeaderCache.migrateLegacyEntryIfNeededForTesting(provider: provider) == nil) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) } @Test func `legacy URL override supports concurrent teardown reads`() { let legacyBases = [ FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), ] defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } DispatchQueue.concurrentPerform(iterations: 5000) { index in if index.isMultiple(of: 3) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[index % legacyBases.count]) } else if index.isMultiple(of: 5) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } else { _ = CookieHeaderCache.legacyURLForTesting(provider: .codex) } } CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[0]) #expect( CookieHeaderCache.legacyURLForTesting(provider: .codex)