The file /Users/neog/Apps/macOS/GhostWriter/GhostWriter/Services/Security/KeychainService.swift has been updated. Here's the result of running `cat -n` on a snippet of the edited file: 1→import Foundation 2→import Security 3→ 4→enum KeychainService { 5→ private static let service = AppConstants.App.bundleId 6→ 7→ enum Key: String, CaseIterable { 8→ case claudeAPIKey = "claude_api_key" 9→ } 10→ 11→ // MARK: - Save 12→ 13→ @discardableResult 14→ static func save(_ value: String, for key: Key) -> Bool { 15→ guard let data = value.data(using: .utf8) else { return false } 16→ 17→ // Delete existing item first 18→ delete(key) 19→ 20→ let query: [String: Any] = [ 21→ kSecClass as String: kSecClassGenericPassword, 22→ kSecAttrService as String: service, 23→ kSecAttrAccount as String: key.rawValue, 24→ kSecValueData as String: data, 25→ kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly 26→ ] 27→ 28→ let status = SecItemAdd(query as CFDictionary, nil) 29→ return status == errSecSuccess 30→ } 31→ 32→ // MARK: - Get 33→ 34→ static func get(_ key: Key) -> String? { 35→ let query: [String: Any] = [ 36→ kSecClass as String: kSecClassGenericPassword, 37→ kSecAttrService as String: service, 38→ kSecAttrAccount as String: key.rawValue, 39→ kSecReturnData as String: true, 40→ kSecMatchLimit as String: kSecMatchLimitOne 41→ ] 42→ 43→ var result: AnyObject? 44→ let status = SecItemCopyMatching(query as CFDictionary, &result) 45→ 46→ guard status == errSecSuccess, 47→ let data = result as? Data, 48→ let value = String(data: data, encoding: .utf8) else { 49→ return nil 50→ } 51→ 52→ return value 53→ } 54→ 55→ // MARK: - Delete 56→ 57→ @discardableResult 58→ static func delete(_ key: Key) -> Bool { 59→ let query: [String: Any] = [ 60→ kSecClass as String: kSecClassGenericPassword, 61→ kSecAttrService as String: service, 62→ kSecAttrAccount as String: key.rawValue 63→ ] 64→ 65→ let status = SecItemDelete(query as CFDictionary) 66→ return status == errSecSuccess || status == errSecItemNotFound 67→ } 68→ 69→ // MARK: - Helpers 70→ 71→ static func exists(_ key: Key) -> Bool { 72→ get(key) != nil && !get(key)!.isEmpty 73→ } 74→ 75→ static func deleteAll() { 76→ Key.allCases.forEach { delete($0) } 77→ } 78→ 79→ // MARK: - Convenience 80→ 81→ static var hasClaudeAPIKey: Bool { 82→ exists(.claudeAPIKey) 83→ } 84→ 85→ static var claudeAPIKey: String? { 86→ get { get(.claudeAPIKey) } 87→ set { 88→ if let value = newValue { 89→ save(value, for: .claudeAPIKey) 90→ } else { 91→ delete(.claudeAPIKey) 92→ } 93→ } 94→ } 95→} 96→