import Foundationpublic enum CodexIdentity: Codable, Equatable, Sendable { case providerAccount(id: String) // Normal OAuth auth should resolve to a provider account ID. Email-only identity is kept as a // migration/hardening fallback for partial auth payloads, not as the primary steady-state path. case emailOnly(normalizedEmail: String) case unresolved}public enum CodexIdentityResolver { public static func resolve(accountId: String?, email: String?) -> CodexIdentity { if let accountId = normalizeAccountID(accountId) { return .providerAccount(id: accountId) } if let email = Self.normalizeEmail(email) { return .emailOnly(normalizedEmail: email) } return .unresolved } public static func normalizeEmail(_ email: String?) -> String? { guard let email = email?.trimmingCharacters(in: .whitespacesAndNewlines), !email.isEmpty else { return nil } return email.lowercased() } public static func normalizeAccountID(_ accountId: String?) -> String? { guard let accountId = accountId?.trimmingCharacters(in: .whitespacesAndNewlines), !accountId.isEmpty else { return nil } return accountId }}public struct CodexAuthBackedAccount: Equatable, Sendable { public let identity: CodexIdentity public let email: String? public let plan: String? public init(identity: CodexIdentity, email: String?, plan: String?) { self.identity = identity self.email = email self.plan = plan }}
import Foundation
public enum CodexIdentity: Codable, Equatable, Sendable {
case providerAccount(id: String)
// Normal OAuth auth should resolve to a provider account ID. Email-only identity is kept as a
// migration/hardening fallback for partial auth payloads, not as the primary steady-state path.
case emailOnly(normalizedEmail: String)
case unresolved
}
public enum CodexIdentityResolver {
public static func resolve(accountId: String?, email: String?) -> CodexIdentity {
if let accountId = normalizeAccountID(accountId) {
return .providerAccount(id: accountId)
}
if let email = Self.normalizeEmail(email) {
return .emailOnly(normalizedEmail: email)
}
return .unresolved
}
public static func normalizeEmail(_ email: String?) -> String? {
guard let email = email?.trimmingCharacters(in: .whitespacesAndNewlines), !email.isEmpty else {
return nil
}
return email.lowercased()
}
public static func normalizeAccountID(_ accountId: String?) -> String? {
guard let accountId = accountId?.trimmingCharacters(in: .whitespacesAndNewlines), !accountId.isEmpty else {
return nil
}
return accountId
}
}
public struct CodexAuthBackedAccount: Equatable, Sendable {
public let identity: CodexIdentity
public let email: String?
public let plan: String?
public init(identity: CodexIdentity, email: String?, plan: String?) {
self.identity = identity
self.email = email
self.plan = plan
}
}