diff --git a/internal/auth/codex/filename.go b/internal/auth/codex/filename.go index f56bdb67e..eba4d02ec 100644 --- a/internal/auth/codex/filename.go +++ b/internal/auth/codex/filename.go @@ -7,9 +7,8 @@ import ( ) // CredentialFileName returns the filename used to persist Codex OAuth credentials. -// When planType is available (e.g. "plus", "team"), it is appended after the email -// as a suffix to disambiguate subscriptions. Team-scoped plans include the account -// hash to avoid overwriting credentials for the same email across multiple teams. +// The account hash is included when available to keep accounts with the same email +// and plan distinct. The legacy email-based format remains the fallback. func CredentialFileName(email, planType, hashAccountID string, includeProviderPrefix bool) string { email = strings.TrimSpace(email) plan := normalizePlanTypeForFilename(planType) @@ -20,18 +19,18 @@ func CredentialFileName(email, planType, hashAccountID string, includeProviderPr prefix = "codex" } - if plan == "" { - return fmt.Sprintf("%s-%s.json", prefix, email) - } else if isTeamScopedPlan(plan) && hashAccountID != "" { + if hashAccountID != "" { + if plan == "" { + return fmt.Sprintf("%s-%s-%s.json", prefix, hashAccountID, email) + } return fmt.Sprintf("%s-%s-%s-%s.json", prefix, hashAccountID, email, plan) } + if plan == "" { + return fmt.Sprintf("%s-%s.json", prefix, email) + } return fmt.Sprintf("%s-%s-%s.json", prefix, email, plan) } -func isTeamScopedPlan(plan string) bool { - return plan == "team" || plan == "k12" -} - func normalizePlanTypeForFilename(planType string) string { planType = strings.TrimSpace(planType) if planType == "" { diff --git a/internal/auth/codex/filename_test.go b/internal/auth/codex/filename_test.go index 3dd26dc74..efa518944 100644 --- a/internal/auth/codex/filename_test.go +++ b/internal/auth/codex/filename_test.go @@ -36,10 +36,18 @@ func TestCredentialFileName(t *testing.T) { want: "codex-user@example.com-k12.json", }, { - name: "plus ignores account hash", + name: "plus includes account hash", email: " user@example.com ", planType: "Plus", - hashAccountID: "abc12345", + hashAccountID: " abc12345 ", + includeProviderPrefix: true, + want: "codex-abc12345-user@example.com-plus.json", + }, + { + name: "plus without account hash falls back to email and plan", + email: "user@example.com", + planType: "plus", + hashAccountID: "", includeProviderPrefix: true, want: "codex-user@example.com-plus.json", }, @@ -49,7 +57,23 @@ func TestCredentialFileName(t *testing.T) { planType: " Team Plan ", hashAccountID: "abc12345", includeProviderPrefix: true, - want: "codex-user@example.com-team-plan.json", + want: "codex-abc12345-user@example.com-team-plan.json", + }, + { + name: "account hash is used without plan", + email: "user@example.com", + planType: "", + hashAccountID: "abc12345", + includeProviderPrefix: true, + want: "codex-abc12345-user@example.com.json", + }, + { + name: "missing plan and account hash falls back to email", + email: "user@example.com", + planType: "", + hashAccountID: "", + includeProviderPrefix: true, + want: "codex-user@example.com.json", }, }