From cb3a1154f88bd48f5d9f46e4daf94341351ae5a4 Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Tue, 10 Feb 2026 15:37:56 -0500 Subject: [PATCH 1/8] reduce AuthStorageOption duplication, refactor the StorageLocation to enum, add missing error handling for some GetOptionValue lines --- internal/commands/auth/credentials.go | 105 ++++++++++-------- .../auth/credentials_storage_fallback_test.go | 9 +- internal/commands/auth/credentials_test.go | 5 +- internal/commands/auth/login_internal.go | 19 +++- internal/commands/auth/logout_internal.go | 29 +++-- internal/commands/auth/use_keychain_test.go | 21 ++-- internal/commands/auth/utils.go | 22 ++-- internal/commands/platform/export_internal.go | 20 +++- internal/customtypes/storage_location_type.go | 11 ++ 9 files changed, 150 insertions(+), 91 deletions(-) create mode 100644 internal/customtypes/storage_location_type.go diff --git a/internal/commands/auth/credentials.go b/internal/commands/auth/credentials.go index 92e383d6..47b835c3 100644 --- a/internal/commands/auth/credentials.go +++ b/internal/commands/auth/credentials.go @@ -46,10 +46,20 @@ func getTokenStorage(authMethod string) (tokenStorage, error) { return newKeychainStorage("pingcli", authMethod) } +// getAuthStorageOption retrieves and normalizes the auth storage option +func getAuthStorageOption() (string, error) { + v, err := profiles.GetOptionValue(options.AuthStorageOption) + if err != nil { + return "", err + } + + return strings.TrimSpace(strings.ToLower(v)), nil +} + // shouldUseKeychain checks if keychain storage should be used based on the storage type // Returns true if storage type is secure_local (default), false for file_system/none func shouldUseKeychain() bool { - v, err := profiles.GetOptionValue(options.AuthStorageOption) + v, err := getAuthStorageOption() if err != nil { return true // default to keychain } @@ -68,8 +78,11 @@ func shouldUseKeychain() bool { // getStorageType returns the appropriate storage type for SDK keychain operations // SDK handles keychain storage, pingcli handles file storage separately func getStorageType() config.StorageType { - v, _ := profiles.GetOptionValue(options.AuthStorageOption) - s := strings.TrimSpace(strings.ToLower(v)) + s, err := getAuthStorageOption() + if err != nil { + return config.StorageTypeSecureLocal + } + if s == string(config.StorageTypeSecureLocal) || s == "" { return config.StorageTypeSecureLocal } @@ -77,17 +90,11 @@ func getStorageType() config.StorageType { return config.StorageTypeNone } -// StorageLocation indicates where credentials were saved -type StorageLocation struct { - Keychain bool - File bool -} - // LoginResult contains the result of a login operation type LoginResult struct { Token *oauth2.Token NewAuth bool - Location StorageLocation + Location customtypes.StorageLocationType } func getConfigForCurrentAuthType() (*config.Configuration, error) { @@ -159,9 +166,9 @@ func getConfigForCurrentAuthType() (*config.Configuration, error) { // SaveTokenForMethod saves an OAuth2 token to file storage using the specified authentication method key // Note: SDK handles keychain storage separately with its own token key format -// Returns StorageLocation indicating where the token was saved -func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation, error) { - location := StorageLocation{} +// Returns StorageLocationType indicating where the token was saved +func SaveTokenForMethod(token *oauth2.Token, authMethod string) (customtypes.StorageLocationType, error) { + var location customtypes.StorageLocationType if token == nil { return location, ErrNilToken @@ -182,9 +189,12 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation } // Check storage option - v, _ := profiles.GetOptionValue(options.AuthStorageOption) + v, err := getAuthStorageOption() + if err != nil { + return location, fmt.Errorf("%s: %w", credentialsErrorPrefix, err) + } - if strings.EqualFold(v, string(config.StorageTypeNone)) { + if v == string(config.StorageTypeNone) { return location, nil } @@ -194,7 +204,7 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation storage, kcErr := getTokenStorage(authMethod) if kcErr == nil { if saveErr := storage.SaveToken(token); saveErr == nil { - location.Keychain = true + location = customtypes.StorageLocationKeychain return location, nil } else { @@ -203,7 +213,7 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation } if err := saveTokenToFile(token, authMethod); err == nil { - location.File = true + location = customtypes.StorageLocationFile return location, nil } else { @@ -215,7 +225,7 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation if err := saveTokenToFile(token, authMethod); err != nil { return location, err } - location.File = true + location = customtypes.StorageLocationFile return location, nil } @@ -224,8 +234,11 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (StorageLocation // Falls back to file storage if keychain operations fail or if --use-keychain=false func LoadTokenForMethod(authMethod string) (*oauth2.Token, error) { // Check if storage is disabled - v, _ := profiles.GetOptionValue(options.AuthStorageOption) - if strings.EqualFold(v, string(config.StorageTypeNone)) { + v, err := getAuthStorageOption() + if err != nil { + return nil, fmt.Errorf("%s: %w", credentialsErrorPrefix, err) + } + if v == string(config.StorageTypeNone) { return nil, ErrTokenStorageDisabled } @@ -369,10 +382,10 @@ func ClearAllTokens() error { // ClearToken removes the cached token for a specific authentication method // Clears from both keychain and file storage -// Returns StorageLocation indicating what was cleared -func ClearToken(authMethod string) (StorageLocation, error) { +// Returns StorageLocationType indicating what was cleared +func ClearToken(authMethod string) (customtypes.StorageLocationType, error) { var errList []error - location := StorageLocation{} + var location customtypes.StorageLocationType // Clear from keychain storage, err := getTokenStorage(authMethod) @@ -383,7 +396,7 @@ func ClearToken(authMethod string) (StorageLocation, error) { Err: err, }) } else { - location.Keychain = true + location = customtypes.StorageLocationKeychain } } @@ -393,8 +406,8 @@ func ClearToken(authMethod string) (StorageLocation, error) { Prefix: credentialsErrorPrefix, Err: err, }) - } else { - location.File = true + } else if location == "" { + location = customtypes.StorageLocationFile } return location, errors.Join(errList...) @@ -554,12 +567,12 @@ func GetDeviceCodeConfiguration() (*config.Configuration, error) { cfg = cfg.WithStorageType(getStorageType()).WithStorageName("pingcli") // Provide optional suffix so SDK keychain entries align with file names - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if strings.TrimSpace(profileName) == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || strings.TrimSpace(profileName) == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeDeviceCode), profileName)) @@ -787,12 +800,12 @@ func GetAuthorizationCodeConfiguration() (*config.Configuration, error) { WithStorageName("pingcli") // Provide optional suffix so SDK keychain entries align with file names - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if strings.TrimSpace(profileName) == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || strings.TrimSpace(profileName) == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeAuthorizationCode), profileName)) @@ -975,12 +988,12 @@ func GetClientCredentialsConfiguration() (*config.Configuration, error) { WithStorageName("pingcli") // Provide optional suffix so SDK keychain entries align with file names - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if strings.TrimSpace(profileName) == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || strings.TrimSpace(profileName) == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeClientCredentials), profileName)) @@ -1056,12 +1069,12 @@ func GetWorkerConfiguration() (*config.Configuration, error) { WithStorageName("pingcli") // Provide optional suffix so SDK keychain entries align with file names - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if strings.TrimSpace(profileName) == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || strings.TrimSpace(profileName) == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeClientCredentials), profileName)) @@ -1131,12 +1144,12 @@ func GetAuthMethodKeyFromConfig(cfg *config.Configuration) (string, error) { } // Build suffix to disambiguate across provider/grant/profile for both keychain and files - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if profileName == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || profileName == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = "pingone" } suffix := fmt.Sprintf("_%s_%s_%s", providerName, string(grantType), profileName) diff --git a/internal/commands/auth/credentials_storage_fallback_test.go b/internal/commands/auth/credentials_storage_fallback_test.go index 2683ddeb..44f6648a 100644 --- a/internal/commands/auth/credentials_storage_fallback_test.go +++ b/internal/commands/auth/credentials_storage_fallback_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/pingidentity/pingcli/internal/constants" + "github.com/pingidentity/pingcli/internal/customtypes" "github.com/pingidentity/pingcli/internal/testing/testutils_koanf" "github.com/stretchr/testify/mock" "golang.org/x/oauth2" @@ -84,10 +85,10 @@ func TestSaveTokenForMethod_FallsBackToFileWhenKeychainSaveFails(t *testing.T) { if err != nil { t.Fatalf("expected no error, got %v", err) } - if location.Keychain { + if location == customtypes.StorageLocationKeychain { t.Fatalf("expected Keychain=false, got true") } - if !location.File { + if location != customtypes.StorageLocationFile { t.Fatalf("expected File=true, got false") } @@ -137,10 +138,10 @@ func TestSaveTokenForMethod_UsesKeychainWhenAvailable(t *testing.T) { mockStorage.AssertExpectations(t) - if !location.Keychain { + if location != customtypes.StorageLocationKeychain { t.Fatalf("expected Keychain=true") } - if location.File { + if location == customtypes.StorageLocationFile { t.Fatalf("expected File=false") } diff --git a/internal/commands/auth/credentials_test.go b/internal/commands/auth/credentials_test.go index e4e436b4..36d5077f 100644 --- a/internal/commands/auth/credentials_test.go +++ b/internal/commands/auth/credentials_test.go @@ -13,6 +13,7 @@ import ( auth_internal "github.com/pingidentity/pingcli/internal/commands/auth" "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/constants" + "github.com/pingidentity/pingcli/internal/customtypes" "github.com/pingidentity/pingcli/internal/profiles" "github.com/pingidentity/pingcli/internal/testing/testutils_koanf" "golang.org/x/oauth2" @@ -775,10 +776,10 @@ func TestSaveTokenForMethod_StorageTypeNone(t *testing.T) { } // Verify neither File nor Keychain storage was used - if location.File { + if location == customtypes.StorageLocationFile { t.Error("Expected File storage to be false, got true") } - if location.Keychain { + if location == customtypes.StorageLocationKeychain { t.Error("Expected Keychain storage to be false, got true") } diff --git a/internal/commands/auth/login_internal.go b/internal/commands/auth/login_internal.go index 9befaa89..1d588174 100644 --- a/internal/commands/auth/login_internal.go +++ b/internal/commands/auth/login_internal.go @@ -46,9 +46,20 @@ func AuthLoginRunE(cmd *cobra.Command, args []string) error { switch provider { case customtypes.ENUM_AUTH_PROVIDER_PINGONE: // Determine desired authentication method - deviceCodeStr, _ := profiles.GetOptionValue(options.AuthMethodDeviceCodeOption) - clientCredentialsStr, _ := profiles.GetOptionValue(options.AuthMethodClientCredentialsOption) - authorizationCodeStr, _ := profiles.GetOptionValue(options.AuthMethodAuthorizationCodeOption) + deviceCodeStr, err := profiles.GetOptionValue(options.AuthMethodDeviceCodeOption) + if err != nil { + return &errs.PingCLIError{Prefix: loginErrorPrefix, Err: err} + } + + clientCredentialsStr, err := profiles.GetOptionValue(options.AuthMethodClientCredentialsOption) + if err != nil { + return &errs.PingCLIError{Prefix: loginErrorPrefix, Err: err} + } + + authorizationCodeStr, err := profiles.GetOptionValue(options.AuthMethodAuthorizationCodeOption) + if err != nil { + return &errs.PingCLIError{Prefix: loginErrorPrefix, Err: err} + } flagProvided := deviceCodeStr == "true" || clientCredentialsStr == "true" || authorizationCodeStr == "true" @@ -186,7 +197,7 @@ func performLoginByConfiguredType(ctx context.Context, authType, profileName str } // displayLoginSuccess displays the successful login message -func displayLoginSuccess(token *oauth2.Token, newAuth bool, location StorageLocation, selectedMethod, profileName string) { +func displayLoginSuccess(token *oauth2.Token, newAuth bool, location customtypes.StorageLocationType, selectedMethod, profileName string) { if newAuth { // Build storage location message storageMsg := formatStorageLocation(location) diff --git a/internal/commands/auth/logout_internal.go b/internal/commands/auth/logout_internal.go index 823a7eae..3ad4c147 100644 --- a/internal/commands/auth/logout_internal.go +++ b/internal/commands/auth/logout_internal.go @@ -15,14 +15,29 @@ import ( "github.com/spf13/cobra" ) +var ( + logoutErrorPrefix = "failed to logout" +) + // AuthLogoutRunE implements the logout command logic, clearing credentials from both // keychain and file storage. If no grant type flag is provided, clears all tokens. // If a specific grant type flag is provided, clears only that method's token. func AuthLogoutRunE(cmd *cobra.Command, args []string) error { // Check if any grant type flags were provided - deviceCodeStr, _ := profiles.GetOptionValue(options.AuthMethodDeviceCodeOption) - clientCredentialsStr, _ := profiles.GetOptionValue(options.AuthMethodClientCredentialsOption) - authorizationCodeStr, _ := profiles.GetOptionValue(options.AuthMethodAuthorizationCodeOption) + deviceCodeStr, err := profiles.GetOptionValue(options.AuthMethodDeviceCodeOption) + if err != nil { + return &errs.PingCLIError{Prefix: logoutErrorPrefix, Err: err} + } + + clientCredentialsStr, err := profiles.GetOptionValue(options.AuthMethodClientCredentialsOption) + if err != nil { + return &errs.PingCLIError{Prefix: logoutErrorPrefix, Err: err} + } + + authorizationCodeStr, err := profiles.GetOptionValue(options.AuthMethodAuthorizationCodeOption) + if err != nil { + return &errs.PingCLIError{Prefix: logoutErrorPrefix, Err: err} + } flagProvided := deviceCodeStr == "true" || clientCredentialsStr == "true" || authorizationCodeStr == "true" @@ -147,12 +162,12 @@ func GetAuthMethodKey(authMethod string) (string, error) { } // Build suffix to disambiguate across provider/grant/profile for both keychain and files - profileName, _ := profiles.GetOptionValue(options.RootActiveProfileOption) - if profileName == "" { + profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil || profileName == "" { profileName = "default" } - providerName, _ := profiles.GetOptionValue(options.AuthProviderOption) - if strings.TrimSpace(providerName) == "" { + providerName, err := profiles.GetOptionValue(options.AuthProviderOption) + if err != nil || strings.TrimSpace(providerName) == "" { providerName = "pingone" } suffix := fmt.Sprintf("_%s_%s_%s", providerName, string(grantType), profileName) diff --git a/internal/commands/auth/use_keychain_test.go b/internal/commands/auth/use_keychain_test.go index 3367ef55..5034486f 100644 --- a/internal/commands/auth/use_keychain_test.go +++ b/internal/commands/auth/use_keychain_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/pingidentity/pingcli/internal/customtypes" "github.com/pingidentity/pingcli/internal/testing/testutils_koanf" svcOAuth2 "github.com/pingidentity/pingone-go-client/oauth2" "golang.org/x/oauth2" @@ -40,8 +41,8 @@ func TestSaveTokenForMethod_WithKeychainDisabled(t *testing.T) { } // Verify location indicates file storage only - if !location.File || location.Keychain { - t.Errorf("Expected file storage only (File=true, Keychain=false), got %+v", location) + if location != customtypes.StorageLocationFile { + t.Errorf("Expected file storage only, got %+v", location) } // Verify token was saved to file @@ -84,9 +85,9 @@ func TestSaveTokenForMethod_WithKeychainEnabled(t *testing.T) { } else { t.Logf("Token saved to: %v", location) - // If it's expected to be in keychain (location.Keychain=true), we must manually save it there + // If it's expected to be in keychain (location == StorageLocationKeychain), we must manually save it there // because SaveTokenForMethod doesn't actually perform the save (it assumes SDK did it) - if location.Keychain { + if location == customtypes.StorageLocationKeychain { storage, sErr := svcOAuth2.NewKeychainStorage("pingcli", authMethod) if sErr != nil { if strings.Contains(sErr.Error(), "keychain") || strings.Contains(sErr.Error(), "freedesktop") { @@ -224,8 +225,8 @@ func TestShouldUseKeychain_Default(t *testing.T) { } else { t.Logf("Token saved with default settings to: %v", location) - // If it's expected to be in keychain (location.Keychain=true), we must manually save it there - if location.Keychain { + // If it's expected to be in keychain (location == StorageLocationKeychain), we must manually save it there + if location == customtypes.StorageLocationKeychain { storage, sErr := svcOAuth2.NewKeychainStorage("pingcli", authMethod) if sErr != nil { if strings.Contains(sErr.Error(), "keychain") || strings.Contains(sErr.Error(), "freedesktop") { @@ -344,8 +345,8 @@ func TestSaveTokenForMethod_FileStorageFallback(t *testing.T) { } else { t.Logf("Token saved - fallback test to: %v", location) - // If it's expected to be in keychain (location.Keychain=true), we must manually save it there - if location.Keychain { + // If it's expected to be in keychain (location == StorageLocationKeychain), we must manually save it there + if location == customtypes.StorageLocationKeychain { storage, sErr := svcOAuth2.NewKeychainStorage("pingcli", authMethod) if sErr == nil { // Don't skip here if save fails, because we are testing fallback? @@ -427,8 +428,8 @@ func TestEnvironmentVariable_FileStorage(t *testing.T) { } // Verify location indicates file storage - if !location.File || location.Keychain { - t.Errorf("Expected file storage with env var (File=true, Keychain=false), got %+v", location) + if location != customtypes.StorageLocationFile { + t.Errorf("Expected file storage with env var, got %+v", location) } // Verify token was saved to file (since file-storage is true) diff --git a/internal/commands/auth/utils.go b/internal/commands/auth/utils.go index 56cc9d2b..4c058f54 100644 --- a/internal/commands/auth/utils.go +++ b/internal/commands/auth/utils.go @@ -4,7 +4,6 @@ package auth_internal import ( "fmt" - "strings" "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/customtypes" @@ -44,19 +43,14 @@ func applyRegionConfiguration(cfg *config.Configuration) (*config.Configuration, } // formatStorageLocation returns a human-friendly message for where credentials were cleared -// based on StorageLocation. -func formatStorageLocation(location StorageLocation) string { - var locs []string - if location.Keychain { - locs = append(locs, "keychain") - } - if location.File { - locs = append(locs, "file storage") - } - - if len(locs) == 0 { +// based on StorageLocationType. +func formatStorageLocation(location customtypes.StorageLocationType) string { + switch location { + case customtypes.StorageLocationKeychain: + return "keychain" + case customtypes.StorageLocationFile: + return "file storage" + default: return "storage" } - - return strings.Join(locs, " and ") } diff --git a/internal/commands/platform/export_internal.go b/internal/commands/platform/export_internal.go index b5194f83..45a73356 100644 --- a/internal/commands/platform/export_internal.go +++ b/internal/commands/platform/export_internal.go @@ -345,9 +345,18 @@ func initPingOneApiClient(ctx context.Context, pingcliVersion string) (err error return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: ErrNilContext} } - workerClientID, _ := profiles.GetOptionValue(options.PingOneAuthenticationWorkerClientIDOption) - workerClientSecret, _ := profiles.GetOptionValue(options.PingOneAuthenticationWorkerClientSecretOption) - workerEnvironmentID, _ := profiles.GetOptionValue(options.PingOneAuthenticationWorkerEnvironmentIDOption) + workerClientID, err := profiles.GetOptionValue(options.PingOneAuthenticationWorkerClientIDOption) + if err != nil { + return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: err} + } + workerClientSecret, err := profiles.GetOptionValue(options.PingOneAuthenticationWorkerClientSecretOption) + if err != nil { + return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: err} + } + workerEnvironmentID, err := profiles.GetOptionValue(options.PingOneAuthenticationWorkerEnvironmentIDOption) + if err != nil { + return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: err} + } regionCode, err := profiles.GetOptionValue(options.PingOneRegionCodeOption) if err != nil { return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: err} @@ -357,7 +366,10 @@ func initPingOneApiClient(ctx context.Context, pingcliVersion string) (err error return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: ErrRegionCodeRequired} } - authType, _ := profiles.GetOptionValue(options.PingOneAuthenticationTypeOption) + authType, err := profiles.GetOptionValue(options.PingOneAuthenticationTypeOption) + if err != nil { + return &errs.PingCLIError{Prefix: exportErrorPrefix, Err: err} + } userAgent := fmt.Sprintf("pingcli/%s", pingcliVersion) if v := strings.TrimSpace(os.Getenv("PINGCLI_PINGONE_APPEND_USER_AGENT")); v != "" { diff --git a/internal/customtypes/storage_location_type.go b/internal/customtypes/storage_location_type.go new file mode 100644 index 00000000..c2a156fa --- /dev/null +++ b/internal/customtypes/storage_location_type.go @@ -0,0 +1,11 @@ +// Copyright © 2026 Ping Identity Corporation + +package customtypes + +// StorageLocationType defines the type of storage where credentials are saved +type StorageLocationType string + +const ( + StorageLocationKeychain StorageLocationType = "keychain" + StorageLocationFile StorageLocationType = "file" +) From 81d7bc32e85cca4f1543b089cfc0a81f64b630fd Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Tue, 10 Feb 2026 17:34:25 -0500 Subject: [PATCH 2/8] remove login code duplication --- internal/commands/auth/credentials.go | 281 +++++--------------------- 1 file changed, 52 insertions(+), 229 deletions(-) diff --git a/internal/commands/auth/credentials.go b/internal/commands/auth/credentials.go index 47b835c3..7c8c71f9 100644 --- a/internal/commands/auth/credentials.go +++ b/internal/commands/auth/credentials.go @@ -413,16 +413,8 @@ func ClearToken(authMethod string) (customtypes.StorageLocationType, error) { return location, errors.Join(errList...) } -// PerformDeviceCodeLogin performs device code authentication, returning the result -func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { - cfg, err := GetDeviceCodeConfiguration() - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - +// performLogin consolidates common authentication logic for different grant types +func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcOAuth2.GrantType, defaultTokenKey string) (*LoginResult, error) { // Get profile name for token key generation profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) if err != nil { @@ -435,16 +427,14 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE // Default to pingone } - // Client ID and environment ID no longer needed for manual key generation - - // Set grant type to device code - cfg = cfg.WithGrantType(svcOAuth2.GrantTypeDeviceCode) + // Set grant type + cfg = cfg.WithGrantType(grantType) // Use SDK-consistent token key generation to avoid mismatches tokenKey, err := GetAuthMethodKeyFromConfig(cfg) if err != nil || tokenKey == "" { // Fallback to simple key if generation fails - tokenKey = deviceCodeTokenKey + tokenKey = defaultTokenKey } // Check if we have a valid cached token before calling TokenSource @@ -473,17 +463,35 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { if !shouldUseKeychain() { if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.RefreshToken != "" { endpoints, eerr := cfg.AuthEndpoints() - if eerr == nil && cfg.Auth.DeviceCode != nil && cfg.Auth.DeviceCode.DeviceCodeClientID != nil { - var scopes []string - if cfg.Auth.DeviceCode.DeviceCodeScopes != nil { - scopes = *cfg.Auth.DeviceCode.DeviceCodeScopes + if eerr == nil { + var oauthCfg *oauth2.Config + switch grantType { + case svcOAuth2.GrantTypeDeviceCode: + if cfg.Auth.DeviceCode != nil && cfg.Auth.DeviceCode.DeviceCodeClientID != nil { + var scopes []string + if cfg.Auth.DeviceCode.DeviceCodeScopes != nil { + scopes = *cfg.Auth.DeviceCode.DeviceCodeScopes + } + oauthCfg = &oauth2.Config{ClientID: *cfg.Auth.DeviceCode.DeviceCodeClientID, Endpoint: endpoints.Endpoint, Scopes: scopes} + } + case svcOAuth2.GrantTypeAuthorizationCode: + if cfg.Auth.AuthorizationCode != nil && cfg.Auth.AuthorizationCode.AuthorizationCodeClientID != nil { + var scopes []string + if cfg.Auth.AuthorizationCode.AuthorizationCodeScopes != nil { + scopes = *cfg.Auth.AuthorizationCode.AuthorizationCodeScopes + } + oauthCfg = &oauth2.Config{ClientID: *cfg.Auth.AuthorizationCode.AuthorizationCodeClientID, Endpoint: endpoints.Endpoint, Scopes: scopes} + } + } + + if oauthCfg != nil { + baseTS := oauthCfg.TokenSource(ctx, existingToken) + tokenSource = oauth2.ReuseTokenSource(nil, baseTS) } - oauthCfg := &oauth2.Config{ClientID: *cfg.Auth.DeviceCode.DeviceCodeClientID, Endpoint: endpoints.Endpoint, Scopes: scopes} - baseTS := oauthCfg.TokenSource(ctx, existingToken) - tokenSource = oauth2.ReuseTokenSource(nil, baseTS) } } } + // Fallback to SDK token source if we didn't create a seeded one if tokenSource == nil { var tsErr error @@ -495,12 +503,6 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { } } } - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } // Get token (SDK will return cached token if valid, or perform new authentication) token, err := tokenSource.Token() @@ -513,7 +515,13 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { // Clean up old token files for this grant type and profile (in case configuration changed) // Ignore errors from cleanup - we still want to save the new token - _ = clearAllTokenFilesForGrantType(providerName, string(svcOAuth2.GrantTypeDeviceCode), profileName) + err = clearAllTokenFilesForGrantType(providerName, string(grantType), profileName) + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: fmt.Errorf("failed to clean up old token files: %w", err), + } + } // Save token using our own storage logic (handles both file and keychain based on flags) location, err := SaveTokenForMethod(token, tokenKey) @@ -529,7 +537,6 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { // If expiry is different, new auth was performed isNewAuth := existingTokenExpiry == nil || !token.Expiry.Equal(*existingTokenExpiry) - // NewAuth indicates whether new authentication was performed return &LoginResult{ Token: token, NewAuth: isNewAuth, @@ -537,6 +544,19 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { }, nil } +// PerformDeviceCodeLogin performs device code authentication, returning the result +func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { + cfg, err := GetDeviceCodeConfiguration() + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + + return performLogin(ctx, cfg, svcOAuth2.GrantTypeDeviceCode, deviceCodeTokenKey) +} + // GetDeviceCodeConfiguration builds a device code authentication configuration from the CLI profile options func GetDeviceCodeConfiguration() (*config.Configuration, error) { cfg := config.NewConfiguration() @@ -619,118 +639,7 @@ func PerformAuthorizationCodeLogin(ctx context.Context) (*LoginResult, error) { } } - // Get profile name for token key generation - profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil { - profileName = "default" // Fallback to default if we can't get profile name - } - - // Get service name for token key generation - providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { - providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE // Default to pingone - } - - // Client ID and environment ID no longer needed for manual key generation - - // Set grant type to authorization code - cfg = cfg.WithGrantType(svcOAuth2.GrantTypeAuthorizationCode) - - // Use SDK-consistent token key generation to avoid mismatches - tokenKey, err := GetAuthMethodKeyFromConfig(cfg) - if err != nil || tokenKey == "" { - // Fallback to simple key if generation fails - tokenKey = authorizationCodeTokenKey - } - - // Check if we have a valid cached token before calling TokenSource - // Store the existing token's expiry to compare later - var existingTokenExpiry *time.Time - - // First try SDK keychain storage if enabled - if shouldUseKeychain() { - keychainStorage, err := svcOAuth2.NewKeychainStorage("pingcli", tokenKey) - if err == nil { - if existingToken, err := keychainStorage.LoadToken(); err == nil && existingToken != nil && existingToken.Valid() { - existingTokenExpiry = &existingToken.Expiry - } - } - } - - // If not found in keychain, check file storage - if existingTokenExpiry == nil { - if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.Valid() { - existingTokenExpiry = &existingToken.Expiry - } - } - - // If using file storage and we have a refresh token, seed refresh via oauth2.ReuseTokenSource - var tokenSource oauth2.TokenSource - if !shouldUseKeychain() { - if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.RefreshToken != "" { - endpoints, eerr := cfg.AuthEndpoints() - if eerr == nil && cfg.Auth.AuthorizationCode != nil && cfg.Auth.AuthorizationCode.AuthorizationCodeClientID != nil { - var scopes []string - if cfg.Auth.AuthorizationCode.AuthorizationCodeScopes != nil { - scopes = *cfg.Auth.AuthorizationCode.AuthorizationCodeScopes - } - oauthCfg := &oauth2.Config{ClientID: *cfg.Auth.AuthorizationCode.AuthorizationCodeClientID, Endpoint: endpoints.Endpoint, Scopes: scopes} - baseTS := oauthCfg.TokenSource(ctx, existingToken) - tokenSource = oauth2.ReuseTokenSource(nil, baseTS) - } - } - } - // Fallback to SDK token source if we didn't create a seeded one - if tokenSource == nil { - var tsErr error - tokenSource, tsErr = cfg.TokenSource(ctx) - if tsErr != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: tsErr, - } - } - } - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Get token (SDK will return cached token if valid, or perform new authentication) - token, err := tokenSource.Token() - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Clean up old token files for this grant type and profile (in case configuration changed) - // Ignore errors from cleanup - we still want to save the new token - _ = clearAllTokenFilesForGrantType(providerName, string(svcOAuth2.GrantTypeAuthorizationCode), profileName) - - // Save token using our own storage logic (handles both file and keychain based on flags) - location, err := SaveTokenForMethod(token, tokenKey) - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Determine if this was new authentication - // If we had an existing token with the same expiry, it's cached - // If expiry is different, new auth was performed - isNewAuth := existingTokenExpiry == nil || !token.Expiry.Equal(*existingTokenExpiry) - - // NewAuth indicates whether new authentication was performed - return &LoginResult{ - Token: token, - NewAuth: isNewAuth, - Location: location, - }, nil + return performLogin(ctx, cfg, svcOAuth2.GrantTypeAuthorizationCode, authorizationCodeTokenKey) } // GetAuthorizationCodeConfiguration builds an authorization code authentication configuration from the CLI profile options @@ -852,93 +761,7 @@ func PerformClientCredentialsLogin(ctx context.Context) (*LoginResult, error) { } } - // Get profile name for token key generation - profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil { - profileName = "default" // Fallback to default if we can't get profile name - } - - // Get service name for token key generation - providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { - providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE // Default to pingone - } - - // Client ID and environment ID no longer needed for manual key generation - - // Set grant type to client credentials - cfg = cfg.WithGrantType(svcOAuth2.GrantTypeClientCredentials) - - // Use SDK-consistent token key generation to avoid mismatches - tokenKey, err := GetAuthMethodKeyFromConfig(cfg) - if err != nil || tokenKey == "" { - // Fallback to simple key if generation fails - tokenKey = clientCredentialsTokenKey - } - - // Check if we have a valid cached token before calling TokenSource - // Store the existing token's expiry to compare later - var existingTokenExpiry *time.Time - - // First try SDK keychain storage if enabled - if shouldUseKeychain() { - keychainStorage, err := svcOAuth2.NewKeychainStorage("pingcli", tokenKey) - if err == nil { - if existingToken, err := keychainStorage.LoadToken(); err == nil && existingToken != nil && existingToken.Valid() { - existingTokenExpiry = &existingToken.Expiry - } - } - } - - // If not found in keychain, check file storage - if existingTokenExpiry == nil { - if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.Valid() { - existingTokenExpiry = &existingToken.Expiry - } - } - - // Get token source - SDK handles keychain storage based on configuration - tokenSource, err := cfg.TokenSource(ctx) - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Get token (SDK will return cached token if valid, or perform new authentication) - token, err := tokenSource.Token() - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Clean up old token files for this grant type and profile (in case configuration changed) - // Ignore errors from cleanup - we still want to save the new token - _ = clearAllTokenFilesForGrantType(providerName, string(svcOAuth2.GrantTypeClientCredentials), profileName) - - // Save token using our own storage logic (handles both file and keychain based on flags) - location, err := SaveTokenForMethod(token, tokenKey) - if err != nil { - return nil, &errs.PingCLIError{ - Prefix: credentialsErrorPrefix, - Err: err, - } - } - - // Determine if this was new authentication - // If we had an existing token with the same expiry, it's cached - // If expiry is different, new auth was performed - isNewAuth := existingTokenExpiry == nil || !token.Expiry.Equal(*existingTokenExpiry) - - // NewAuth indicates whether new authentication was performed - return &LoginResult{ - Token: token, - NewAuth: isNewAuth, - Location: location, - }, nil + return performLogin(ctx, cfg, svcOAuth2.GrantTypeClientCredentials, clientCredentialsTokenKey) } // GetClientCredentialsConfiguration builds a client credentials authentication configuration from the CLI profile options From e09a03b390c1ce09c39a968c604782c7e6f11957 Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Wed, 11 Feb 2026 12:45:43 -0500 Subject: [PATCH 3/8] Revised error handling, ClearToken method cleanup, updated test checks --- internal/commands/auth/credentials.go | 144 +++++++++++------- .../auth/credentials_storage_fallback_test.go | 8 +- internal/commands/auth/credentials_test.go | 2 +- internal/commands/auth/logout_internal.go | 4 +- internal/commands/auth/use_keychain_test.go | 12 +- internal/constants/constants.go | 2 + 6 files changed, 102 insertions(+), 70 deletions(-) diff --git a/internal/commands/auth/credentials.go b/internal/commands/auth/credentials.go index 7c8c71f9..93ce2421 100644 --- a/internal/commands/auth/credentials.go +++ b/internal/commands/auth/credentials.go @@ -10,6 +10,7 @@ import ( "time" "github.com/pingidentity/pingcli/internal/configuration/options" + "github.com/pingidentity/pingcli/internal/constants" "github.com/pingidentity/pingcli/internal/customtypes" "github.com/pingidentity/pingcli/internal/errs" "github.com/pingidentity/pingcli/internal/profiles" @@ -43,14 +44,17 @@ var newKeychainStorage = func(serviceName, username string) (tokenStorage, error // getTokenStorage returns the appropriate keychain storage instance for the given authentication method func getTokenStorage(authMethod string) (tokenStorage, error) { - return newKeychainStorage("pingcli", authMethod) + return newKeychainStorage(constants.PingCliName, authMethod) } // getAuthStorageOption retrieves and normalizes the auth storage option func getAuthStorageOption() (string, error) { v, err := profiles.GetOptionValue(options.AuthStorageOption) if err != nil { - return "", err + return "", &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } } return strings.TrimSpace(strings.ToLower(v)), nil @@ -58,20 +62,20 @@ func getAuthStorageOption() (string, error) { // shouldUseKeychain checks if keychain storage should be used based on the storage type // Returns true if storage type is secure_local (default), false for file_system/none -func shouldUseKeychain() bool { +func shouldUseKeychain() (bool, error) { v, err := getAuthStorageOption() if err != nil { - return true // default to keychain + return false, err } switch v { case string(config.StorageTypeSecureLocal): - return true + return true, nil case string(config.StorageTypeFileSystem), string(config.StorageTypeNone), string(config.StorageTypeSecureRemote): - return false + return false, nil default: // Unrecognized: lean secure by not disabling keychain - return true + return true, nil } } @@ -79,11 +83,7 @@ func shouldUseKeychain() bool { // SDK handles keychain storage, pingcli handles file storage separately func getStorageType() config.StorageType { s, err := getAuthStorageOption() - if err != nil { - return config.StorageTypeSecureLocal - } - - if s == string(config.StorageTypeSecureLocal) || s == "" { + if err != nil || s == string(config.StorageTypeSecureLocal) || s == "" { return config.StorageTypeSecureLocal } // For file_system/none/secure_remote, avoid SDK persistence (pingcli manages file persistence) @@ -191,7 +191,10 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (customtypes.Sto // Check storage option v, err := getAuthStorageOption() if err != nil { - return location, fmt.Errorf("%s: %w", credentialsErrorPrefix, err) + return location, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } } if v == string(config.StorageTypeNone) { @@ -200,7 +203,11 @@ func SaveTokenForMethod(token *oauth2.Token, authMethod string) (customtypes.Sto // When keychain is enabled, attempt to save to keychain. // If keychain is unavailable or save fails, fall back to file storage. - if shouldUseKeychain() { + useKeychain, err := shouldUseKeychain() + if err != nil { + return location, err + } + if useKeychain { storage, kcErr := getTokenStorage(authMethod) if kcErr == nil { if saveErr := storage.SaveToken(token); saveErr == nil { @@ -236,14 +243,21 @@ func LoadTokenForMethod(authMethod string) (*oauth2.Token, error) { // Check if storage is disabled v, err := getAuthStorageOption() if err != nil { - return nil, fmt.Errorf("%s: %w", credentialsErrorPrefix, err) + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } } if v == string(config.StorageTypeNone) { return nil, ErrTokenStorageDisabled } // Check if user disabled keychain - if !shouldUseKeychain() { + useKeychain, err := shouldUseKeychain() + if err != nil { + return nil, err + } + if !useKeychain { // Directly load from file storage return loadTokenFromFile(authMethod) } @@ -284,7 +298,11 @@ func GetValidTokenSource(ctx context.Context) (oauth2.TokenSource, error) { if cfg != nil { // If using file storage, try to seed refresh from existing file token before new login - if !shouldUseKeychain() { + useKeychain, skErr := shouldUseKeychain() + if skErr != nil { + return nil, skErr + } + if !useKeychain { tokenKey, err := GetAuthMethodKeyFromConfig(cfg) if err == nil && tokenKey != "" { if existingToken, ferr := loadTokenFromFile(tokenKey); ferr == nil && existingToken != nil && existingToken.RefreshToken != "" { @@ -338,7 +356,11 @@ func GetValidTokenSource(ctx context.Context) (oauth2.TokenSource, error) { // If we are not using keychain (e.g. file storage), we need to wrap the source // to capture and persist the token to file when it is refreshed or created. // The SDK's TokenSource only handles keychain persistence internally. - if !shouldUseKeychain() { + useKeychain, skErr = shouldUseKeychain() + if skErr != nil { + return nil, skErr + } + if !useKeychain { tokenKey, err := GetAuthMethodKeyFromConfig(cfg) if err == nil { return &filePersistingTokenSource{ @@ -366,7 +388,7 @@ func ClearAllTokens() error { // First, attempt to clear ALL keychain entries for the pingcli service // This ensures we clean up tokens from previous configurations (stale Client IDs, etc.) // We use a dummy username because the constructor requires it, but ClearAllTokens operates at service level - if ks, err := newKeychainStorage("pingcli", "clearAllTokens"); err == nil { + if ks, err := newKeychainStorage(constants.PingCliName, "clearAllTokens"); err == nil { if err := ks.ClearAllTokens(); err != nil { errs = append(errs, err) } @@ -382,10 +404,8 @@ func ClearAllTokens() error { // ClearToken removes the cached token for a specific authentication method // Clears from both keychain and file storage -// Returns StorageLocationType indicating what was cleared -func ClearToken(authMethod string) (customtypes.StorageLocationType, error) { +func ClearToken(authMethod string) error { var errList []error - var location customtypes.StorageLocationType // Clear from keychain storage, err := getTokenStorage(authMethod) @@ -395,8 +415,6 @@ func ClearToken(authMethod string) (customtypes.StorageLocationType, error) { Prefix: credentialsErrorPrefix, Err: err, }) - } else { - location = customtypes.StorageLocationKeychain } } @@ -406,11 +424,9 @@ func ClearToken(authMethod string) (customtypes.StorageLocationType, error) { Prefix: credentialsErrorPrefix, Err: err, }) - } else if location == "" { - location = customtypes.StorageLocationFile } - return location, errors.Join(errList...) + return errors.Join(errList...) } // performLogin consolidates common authentication logic for different grant types @@ -418,7 +434,7 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO // Get profile name for token key generation profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) if err != nil { - profileName = "default" // Fallback to default if we can't get profile name + return nil, &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} } // Get service name for token key generation @@ -433,7 +449,7 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO // Use SDK-consistent token key generation to avoid mismatches tokenKey, err := GetAuthMethodKeyFromConfig(cfg) if err != nil || tokenKey == "" { - // Fallback to simple key if generation fails + // Fallback to default key if generation fails, though this shouldn't happen with valid config tokenKey = defaultTokenKey } @@ -442,8 +458,12 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO var existingTokenExpiry *time.Time // First try SDK keychain storage if enabled - if shouldUseKeychain() { - keychainStorage, err := svcOAuth2.NewKeychainStorage("pingcli", tokenKey) + useKeychain, skErr := shouldUseKeychain() + if skErr != nil { + return nil, skErr + } + if useKeychain { + keychainStorage, err := svcOAuth2.NewKeychainStorage(constants.PingCliName, tokenKey) if err == nil { if existingToken, err := keychainStorage.LoadToken(); err == nil && existingToken != nil && existingToken.Valid() { existingTokenExpiry = &existingToken.Expiry @@ -451,19 +471,14 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO } } - // If not found in keychain, check file storage - if existingTokenExpiry == nil { - if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.Valid() { - existingTokenExpiry = &existingToken.Expiry - } - } - // If using file storage and we have a refresh token, seed refresh via oauth2.ReuseTokenSource var tokenSource oauth2.TokenSource - if !shouldUseKeychain() { + + if !useKeychain { if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.RefreshToken != "" { endpoints, eerr := cfg.AuthEndpoints() if eerr == nil { + grantType := *cfg.Auth.GrantType var oauthCfg *oauth2.Config switch grantType { case svcOAuth2.GrantTypeDeviceCode: @@ -584,12 +599,15 @@ func GetDeviceCodeConfiguration() (*config.Configuration, error) { cfg = cfg.WithDeviceCodeScopes(scopeDefaults) // Configure storage options based on --file-storage flag - cfg = cfg.WithStorageType(getStorageType()).WithStorageName("pingcli") + cfg = cfg.WithStorageType(getStorageType()).WithStorageName(constants.PingCliName) // Provide optional suffix so SDK keychain entries align with file names profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil || strings.TrimSpace(profileName) == "" { - profileName = "default" + if err != nil { + return nil, &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} + } + if strings.TrimSpace(profileName) == "" { + profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) if err != nil || strings.TrimSpace(providerName) == "" { @@ -701,17 +719,20 @@ func GetAuthorizationCodeConfiguration() (*config.Configuration, error) { WithAuthorizationCodeRedirectURI(redirectURI) // This is the default scope. Additional scopes can be appended by the user later if needed. - scopeDefaults := []string{"openid"} + scopeDefaults := []string{constants.OpenIDScope} cfg = cfg.WithAuthorizationCodeScopes(scopeDefaults) // Configure storage options based on --file-storage flag cfg = cfg.WithStorageType(getStorageType()). - WithStorageName("pingcli") + WithStorageName(constants.PingCliName) // Provide optional suffix so SDK keychain entries align with file names profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil || strings.TrimSpace(profileName) == "" { - profileName = "default" + if err != nil { + return nil, &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} + } + if strings.TrimSpace(profileName) == "" { + profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) if err != nil || strings.TrimSpace(providerName) == "" { @@ -803,17 +824,20 @@ func GetClientCredentialsConfiguration() (*config.Configuration, error) { WithClientCredentialsClientSecret(clientSecret) // This is the default scope. Additional scopes can be appended by the user later if needed. - scopeDefaults := []string{"openid"} + scopeDefaults := []string{constants.OpenIDScope} cfg = cfg.WithClientCredentialsScopes(scopeDefaults) // Configure storage options based on --file-storage flag cfg = cfg.WithStorageType(getStorageType()). - WithStorageName("pingcli") + WithStorageName(constants.PingCliName) // Provide optional suffix so SDK keychain entries align with file names profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil || strings.TrimSpace(profileName) == "" { - profileName = "default" + if err != nil { + return nil, &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} + } + if strings.TrimSpace(profileName) == "" { + profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) if err != nil || strings.TrimSpace(providerName) == "" { @@ -885,16 +909,19 @@ func GetWorkerConfiguration() (*config.Configuration, error) { cfg = cfg.WithClientCredentialsClientID(clientID). WithClientCredentialsClientSecret(clientSecret) // Align default scopes with client credentials flow - scopeDefaults := []string{"openid"} + scopeDefaults := []string{constants.OpenIDScope} cfg = cfg.WithClientCredentialsScopes(scopeDefaults) // Configure storage options based on --file-storage flag cfg = cfg.WithStorageType(getStorageType()). - WithStorageName("pingcli") + WithStorageName(constants.PingCliName) // Provide optional suffix so SDK keychain entries align with file names profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil || strings.TrimSpace(profileName) == "" { - profileName = "default" + if err != nil { + return nil, &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} + } + if strings.TrimSpace(profileName) == "" { + profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) if err != nil || strings.TrimSpace(providerName) == "" { @@ -968,12 +995,15 @@ func GetAuthMethodKeyFromConfig(cfg *config.Configuration) (string, error) { // Build suffix to disambiguate across provider/grant/profile for both keychain and files profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) - if err != nil || profileName == "" { - profileName = "default" + if err != nil { + return "", &errs.PingCLIError{Prefix: loginInteractiveErrorPrefix, Err: err} + } + if profileName == "" { + profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) if err != nil || strings.TrimSpace(providerName) == "" { - providerName = "pingone" + providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } suffix := fmt.Sprintf("_%s_%s_%s", providerName, string(grantType), profileName) // Use the SDK's GenerateKeychainAccountName with optional suffix diff --git a/internal/commands/auth/credentials_storage_fallback_test.go b/internal/commands/auth/credentials_storage_fallback_test.go index 44f6648a..ff362f07 100644 --- a/internal/commands/auth/credentials_storage_fallback_test.go +++ b/internal/commands/auth/credentials_storage_fallback_test.go @@ -86,10 +86,10 @@ func TestSaveTokenForMethod_FallsBackToFileWhenKeychainSaveFails(t *testing.T) { t.Fatalf("expected no error, got %v", err) } if location == customtypes.StorageLocationKeychain { - t.Fatalf("expected Keychain=false, got true") + t.Fatalf("expected storage location to not be %s", customtypes.StorageLocationKeychain) } if location != customtypes.StorageLocationFile { - t.Fatalf("expected File=true, got false") + t.Fatalf("expected storage location %s, got %s", customtypes.StorageLocationFile, location) } // Verify it actually wrote the expected file under HOME @@ -139,10 +139,10 @@ func TestSaveTokenForMethod_UsesKeychainWhenAvailable(t *testing.T) { mockStorage.AssertExpectations(t) if location != customtypes.StorageLocationKeychain { - t.Fatalf("expected Keychain=true") + t.Fatalf("expected storage location %s, got %s", customtypes.StorageLocationKeychain, location) } if location == customtypes.StorageLocationFile { - t.Fatalf("expected File=false") + t.Fatalf("expected storage location to not be %s", customtypes.StorageLocationFile) } // File should not be written when keychain save succeeds diff --git a/internal/commands/auth/credentials_test.go b/internal/commands/auth/credentials_test.go index 36d5077f..09c48749 100644 --- a/internal/commands/auth/credentials_test.go +++ b/internal/commands/auth/credentials_test.go @@ -265,7 +265,7 @@ func TestClearToken(t *testing.T) { // Test that ClearTokenForMethod doesn't panic when no token exists // This should handle the case where keychain entry doesn't exist - _, err := auth_internal.ClearToken(testKey) + err := auth_internal.ClearToken(testKey) // Should not error when no token exists (handles ErrNotFound) if err != nil { diff --git a/internal/commands/auth/logout_internal.go b/internal/commands/auth/logout_internal.go index 3ad4c147..e4beefac 100644 --- a/internal/commands/auth/logout_internal.go +++ b/internal/commands/auth/logout_internal.go @@ -86,9 +86,9 @@ func AuthLogoutRunE(cmd *cobra.Command, args []string) error { } // Clear only the token for the specified grant type - location, err := ClearToken(tokenKey) + err = ClearToken(tokenKey) if err != nil { - return &errs.PingCLIError{Prefix: credentialsErrorPrefix, Err: fmt.Errorf("failed to clear %s credentials. in %s: %w", authType, formatStorageLocation(location), err)} + return &errs.PingCLIError{Prefix: credentialsErrorPrefix, Err: fmt.Errorf("failed to clear %s credentials: %w", authType, err)} } output.Success(fmt.Sprintf("Successfully logged out and cleared credentials from %s for service '%s' using profile '%s'.", authType, providerName, profileName), nil) diff --git a/internal/commands/auth/use_keychain_test.go b/internal/commands/auth/use_keychain_test.go index 5034486f..453b58df 100644 --- a/internal/commands/auth/use_keychain_test.go +++ b/internal/commands/auth/use_keychain_test.go @@ -73,7 +73,7 @@ func TestSaveTokenForMethod_WithKeychainEnabled(t *testing.T) { authMethod := "test-keychain-enabled" t.Cleanup(func() { - _, _ = ClearToken(authMethod) + _ = ClearToken(authMethod) }) // Save token - should try keychain first @@ -175,7 +175,7 @@ func TestLoadTokenForMethod_FallbackToFileStorage(t *testing.T) { t.Cleanup(func() { _ = clearTokenFromFile(authMethod) - _, _ = ClearToken(authMethod) + _ = ClearToken(authMethod) }) // Save token only to file storage (keychain disabled) @@ -215,7 +215,7 @@ func TestShouldUseKeychain_Default(t *testing.T) { authMethod := "test-default-keychain" t.Cleanup(func() { - _, _ = ClearToken(authMethod) + _ = ClearToken(authMethod) }) // Save token - should try keychain by default @@ -271,7 +271,7 @@ func TestClearToken_ClearsBothStorages(t *testing.T) { authMethod := "test-clear-both-storages" t.Cleanup(func() { - _, _ = ClearToken(authMethod) + _ = ClearToken(authMethod) }) // Save to file storage directly @@ -287,7 +287,7 @@ func TestClearToken_ClearsBothStorages(t *testing.T) { } // Clear token - should remove from both keychain and file storage - _, err = ClearToken(authMethod) + err = ClearToken(authMethod) if err != nil { t.Logf("ClearToken returned error (may be expected if keychain not available): %v", err) } @@ -335,7 +335,7 @@ func TestSaveTokenForMethod_FileStorageFallback(t *testing.T) { authMethod := "test-save-fallback" t.Cleanup(func() { - _, _ = ClearToken(authMethod) + _ = ClearToken(authMethod) }) // Save token - will try keychain first (may succeed or fail depending on environment) diff --git a/internal/constants/constants.go b/internal/constants/constants.go index bb734287..04e55c71 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -6,4 +6,6 @@ const ( PingCliName = "pingcli" PingCliDirName = ".pingcli" CredentialsDirName = "credentials" + DefaultProfileName = "default" + OpenIDScope = "openid" ) From 1d2e8a875435fc32d45f31cd2a637629b66fff36 Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Thu, 12 Feb 2026 11:28:48 -0500 Subject: [PATCH 4/8] Remove unneeded default token keys, Improved handling for GetOptionValue errors, add missing fallback for file storage checking, comment lines corrected --- internal/commands/auth/credentials.go | 83 +++++++++++++++++++-------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/internal/commands/auth/credentials.go b/internal/commands/auth/credentials.go index 93ce2421..b6bc67e7 100644 --- a/internal/commands/auth/credentials.go +++ b/internal/commands/auth/credentials.go @@ -19,13 +19,6 @@ import ( "golang.org/x/oauth2" ) -// Token storage keys for different authentication methods -const ( - deviceCodeTokenKey = "device-code-token" - authorizationCodeTokenKey = "authorization-code-token" // #nosec G101 -- This is a keychain identifier, not a credential - clientCredentialsTokenKey = "client-credentials-token" -) - var ( credentialsErrorPrefix = "failed to manage credentials" tokenManagerErrorPrefix = "failed to manage token" @@ -164,7 +157,7 @@ func getConfigForCurrentAuthType() (*config.Configuration, error) { } } -// SaveTokenForMethod saves an OAuth2 token to file storage using the specified authentication method key +// SaveTokenForMethod saves an OAuth2 token to storage (keychain or file) using the specified authentication method key // Note: SDK handles keychain storage separately with its own token key format // Returns StorageLocationType indicating where the token was saved func SaveTokenForMethod(token *oauth2.Token, authMethod string) (customtypes.StorageLocationType, error) { @@ -379,7 +372,7 @@ func GetValidTokenSource(ctx context.Context) (oauth2.TokenSource, error) { } } -// ClearAllTokens removes all cached tokens from the keychain for all authentication methods. +// ClearAllTokens removes all cached tokens from keychain and file storage for all authentication methods. // This clears tokens from ALL grant types, not just the currently configured one, // to handle cases where users switch between authentication methods func ClearAllTokens() error { @@ -430,7 +423,7 @@ func ClearToken(authMethod string) error { } // performLogin consolidates common authentication logic for different grant types -func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcOAuth2.GrantType, defaultTokenKey string) (*LoginResult, error) { +func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcOAuth2.GrantType) (*LoginResult, error) { // Get profile name for token key generation profileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) if err != nil { @@ -439,7 +432,13 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO // Get service name for token key generation providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE // Default to pingone } @@ -448,9 +447,11 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO // Use SDK-consistent token key generation to avoid mismatches tokenKey, err := GetAuthMethodKeyFromConfig(cfg) - if err != nil || tokenKey == "" { - // Fallback to default key if generation fails, though this shouldn't happen with valid config - tokenKey = defaultTokenKey + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } } // Check if we have a valid cached token before calling TokenSource @@ -471,6 +472,13 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO } } + // If not found in keychain, check file storage + if existingTokenExpiry == nil { + if existingToken, err := loadTokenFromFile(tokenKey); err == nil && existingToken != nil && existingToken.Valid() { + existingTokenExpiry = &existingToken.Expiry + } + } + // If using file storage and we have a refresh token, seed refresh via oauth2.ReuseTokenSource var tokenSource oauth2.TokenSource @@ -529,7 +537,6 @@ func performLogin(ctx context.Context, cfg *config.Configuration, grantType svcO } // Clean up old token files for this grant type and profile (in case configuration changed) - // Ignore errors from cleanup - we still want to save the new token err = clearAllTokenFilesForGrantType(providerName, string(grantType), profileName) if err != nil { return nil, &errs.PingCLIError{ @@ -569,7 +576,7 @@ func PerformDeviceCodeLogin(ctx context.Context) (*LoginResult, error) { } } - return performLogin(ctx, cfg, svcOAuth2.GrantTypeDeviceCode, deviceCodeTokenKey) + return performLogin(ctx, cfg, svcOAuth2.GrantTypeDeviceCode) } // GetDeviceCodeConfiguration builds a device code authentication configuration from the CLI profile options @@ -610,7 +617,13 @@ func GetDeviceCodeConfiguration() (*config.Configuration, error) { profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeDeviceCode), profileName)) @@ -657,7 +670,7 @@ func PerformAuthorizationCodeLogin(ctx context.Context) (*LoginResult, error) { } } - return performLogin(ctx, cfg, svcOAuth2.GrantTypeAuthorizationCode, authorizationCodeTokenKey) + return performLogin(ctx, cfg, svcOAuth2.GrantTypeAuthorizationCode) } // GetAuthorizationCodeConfiguration builds an authorization code authentication configuration from the CLI profile options @@ -735,7 +748,13 @@ func GetAuthorizationCodeConfiguration() (*config.Configuration, error) { profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeAuthorizationCode), profileName)) @@ -782,7 +801,7 @@ func PerformClientCredentialsLogin(ctx context.Context) (*LoginResult, error) { } } - return performLogin(ctx, cfg, svcOAuth2.GrantTypeClientCredentials, clientCredentialsTokenKey) + return performLogin(ctx, cfg, svcOAuth2.GrantTypeClientCredentials) } // GetClientCredentialsConfiguration builds a client credentials authentication configuration from the CLI profile options @@ -840,7 +859,13 @@ func GetClientCredentialsConfiguration() (*config.Configuration, error) { profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeClientCredentials), profileName)) @@ -924,7 +949,13 @@ func GetWorkerConfiguration() (*config.Configuration, error) { profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return nil, &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } cfg = cfg.WithStorageOptionalSuffix(fmt.Sprintf("_%s_%s_%s", providerName, string(svcOAuth2.GrantTypeClientCredentials), profileName)) @@ -1002,7 +1033,13 @@ func GetAuthMethodKeyFromConfig(cfg *config.Configuration) (string, error) { profileName = constants.DefaultProfileName } providerName, err := profiles.GetOptionValue(options.AuthProviderOption) - if err != nil || strings.TrimSpace(providerName) == "" { + if err != nil { + return "", &errs.PingCLIError{ + Prefix: credentialsErrorPrefix, + Err: err, + } + } + if strings.TrimSpace(providerName) == "" { providerName = customtypes.ENUM_AUTH_PROVIDER_PINGONE } suffix := fmt.Sprintf("_%s_%s_%s", providerName, string(grantType), profileName) From caa778655f9a857bd0d79ffd36b257a706eb087e Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Wed, 18 Feb 2026 11:36:32 -0500 Subject: [PATCH 5/8] add changelog entry --- .changelog/pr-157.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/pr-157.txt diff --git a/.changelog/pr-157.txt b/.changelog/pr-157.txt new file mode 100644 index 00000000..a2b0c585 --- /dev/null +++ b/.changelog/pr-157.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +code refactor for storage logic and duplication +``` From 0f9376d92f5db791f2988a0862ff4658612b6e8a Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Wed, 18 Feb 2026 14:11:45 -0500 Subject: [PATCH 6/8] bump golangci-lint tool version, address lint issues --- cmd/root.go | 2 + go.mod | 49 ++++---- go.sum | 119 +++++++++--------- internal/commands/auth/file_storage.go | 6 +- .../auth/login_interactive_internal.go | 3 +- internal/commands/auth/use_keychain_test.go | 3 + internal/commands/license/license_internal.go | 1 + .../commands/platform/export_internal_test.go | 2 +- .../commands/request/request_internal_test.go | 3 +- internal/commands/request/request_pingone.go | 1 + internal/input/input.go | 2 + internal/logger/logger.go | 1 + .../mfa_application_push_credential.go | 2 +- .../identity_provider.go | 1 + .../testutils_terraform/terraform_utils.go | 1 + tools/generate-options-docs/docgen/docgen.go | 8 +- 16 files changed, 106 insertions(+), 98 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 24fd468f..bb108b94 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -174,6 +174,7 @@ func ParseArgsForConfigFile(args []string) string { func checkCfgFileLocation(cfgFile string) { // Check existence of configuration file + //nolint:gosec // G703: Path provided by user via flag is trusted _, err := os.Stat(cfgFile) if os.IsNotExist(err) { // Only create a new configuration file if it is the default configuration file location @@ -193,6 +194,7 @@ func createConfigFile(cfgFile string) { output.Message(fmt.Sprintf("Creating new Ping CLI configuration file at: %s", cfgFile), nil) // MkdirAll does nothing if directories already exist. Create needed directories for config file location. + //nolint:gosec // G703: Path provided by user to create configuration file is trusted err := os.MkdirAll(filepath.Dir(cfgFile), os.FileMode(0700)) if err != nil { output.SystemError(fmt.Sprintf("Failed to make the directory for the new configuration file '%s': %v", cfgFile, err), nil) diff --git a/go.mod b/go.mod index b447152a..0c1d16fc 100644 --- a/go.mod +++ b/go.mod @@ -28,9 +28,9 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 - golang.org/x/mod v0.31.0 + golang.org/x/mod v0.33.0 golang.org/x/oauth2 v0.33.0 - golang.org/x/term v0.38.0 + golang.org/x/term v0.40.0 google.golang.org/grpc v1.76.0 google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 @@ -54,12 +54,12 @@ require ( github.com/BurntSushi/toml v1.6.0 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/MirrexOne/unqueryvet v1.4.0 // indirect + github.com/MirrexOne/unqueryvet v1.5.3 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.21.1 // indirect + github.com/alecthomas/chroma/v2 v2.23.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect - github.com/alexkohler/prealloc v1.0.1 // indirect + github.com/alexkohler/prealloc v1.0.2 // indirect github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect @@ -70,7 +70,7 @@ require ( github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v4 v4.7.0 // indirect - github.com/bombsimon/wsl/v5 v5.3.0 // indirect + github.com/bombsimon/wsl/v5 v5.6.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect github.com/butuzov/ireturn v0.4.0 // indirect @@ -81,7 +81,7 @@ require ( github.com/charithe/durationcheck v0.0.11 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/ansi v0.10.1 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/chzyer/readline v1.5.1 // indirect @@ -98,7 +98,7 @@ require ( github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.18 // indirect + github.com/ghostiam/protogetter v0.3.20 // indirect github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect @@ -107,20 +107,20 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/godoc-lint/godoc-lint v0.11.1 // indirect + github.com/godoc-lint/godoc-lint v0.11.2 // indirect github.com/gofrs/flock v0.13.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint/v2 v2.8.0 // indirect - github.com/golangci/golines v0.14.0 // indirect - github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/golangci-lint/v2 v2.10.1 // indirect + github.com/golangci/golines v0.15.0 // indirect + github.com/golangci/misspell v0.8.0 // indirect github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect @@ -167,7 +167,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.13.0 // indirect + github.com/mgechev/revive v1.14.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -176,7 +176,7 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.21.2 // indirect + github.com/nunnatsa/ginkgolinter v0.23.0 // indirect github.com/oklog/run v1.2.0 // indirect github.com/patrickcping/pingone-go-sdk-v2/credentials v0.12.0 // indirect github.com/patrickcping/pingone-go-sdk-v2/verify v0.10.0 // indirect @@ -202,8 +202,8 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/securego/gosec/v2 v2.22.11 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/securego/gosec/v2 v2.23.0 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -233,20 +233,19 @@ require ( gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.14.0 // indirect go-simpler.org/sloglint v0.11.1 // indirect - go.augendre.info/arangolint v0.3.1 // indirect + go.augendre.info/arangolint v0.4.0 // indirect go.augendre.info/fatcontext v0.9.0 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect - golang.org/x/net v0.48.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect + golang.org/x/net v0.50.0 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect - golang.org/x/text v0.32.0 // indirect - golang.org/x/tools v0.40.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/tools v0.42.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect - honnef.co/go/tools v0.6.1 // indirect + honnef.co/go/tools v0.7.0 // indirect mvdan.cc/gofumpt v0.9.2 // indirect mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect ) diff --git a/go.sum b/go.sum index 06f64bd7..bf99b75b 100644 --- a/go.sum +++ b/go.sum @@ -67,14 +67,14 @@ github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/MirrexOne/unqueryvet v1.4.0 h1:6KAkqqW2KUnkl9Z0VuTphC3IXRPoFqEkJEtyxxHj5eQ= -github.com/MirrexOne/unqueryvet v1.4.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= +github.com/MirrexOne/unqueryvet v1.5.3 h1:LpT3rsH+IY3cQddWF9bg4C7jsbASdGnrOSofY8IPEiw= +github.com/MirrexOne/unqueryvet v1.5.3/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.21.1 h1:FaSDrp6N+3pphkNKU6HPCiYLgm8dbe5UXIXcoBhZSWA= -github.com/alecthomas/chroma/v2 v2.21.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= +github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= +github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= @@ -86,8 +86,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= -github.com/alexkohler/prealloc v1.0.1 h1:A9P1haqowqUxWvU9nk6tQ7YktXIHf+LQM9wPRhuteEE= -github.com/alexkohler/prealloc v1.0.1/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= +github.com/alexkohler/prealloc v1.0.2 h1:MPo8cIkGkZytq7WNH9UHv3DIX1mPz1RatPXnZb0zHWQ= +github.com/alexkohler/prealloc v1.0.2/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -110,8 +110,8 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= -github.com/bombsimon/wsl/v5 v5.3.0 h1:nZWREJFL6U3vgW/B1lfDOigl+tEF6qgs6dGGbFeR0UM= -github.com/bombsimon/wsl/v5 v5.3.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= +github.com/bombsimon/wsl/v5 v5.6.0 h1:4z+/sBqC5vUmSp1O0mS+czxwH9+LKXtCWtHH9rZGQL8= +github.com/bombsimon/wsl/v5 v5.6.0/go.mod h1:Uqt2EfrMj2NV8UGoN1f1Y3m0NpUVCsUdrNCdet+8LvU= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= @@ -137,8 +137,8 @@ github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4p github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= +github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= @@ -195,8 +195,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.18 h1:yEpghRGtP9PjKvVXtEzGpYfQj1Wl/ZehAfU6fr62Lfo= -github.com/ghostiam/protogetter v0.3.18/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= +github.com/ghostiam/protogetter v0.3.20 h1:oW7OPFit2FxZOpmMRPP9FffU4uUpfeE/rEdE1f+MzD0= +github.com/ghostiam/protogetter v0.3.20/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog= github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -236,8 +236,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -245,8 +245,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godoc-lint/godoc-lint v0.11.1 h1:z9as8Qjiy6miRIa3VRymTa+Gt2RLnGICVikcvlUVOaA= -github.com/godoc-lint/godoc-lint v0.11.1/go.mod h1:BAqayheFSuZrEAqCRxgw9MyvsM+S/hZwJbU1s/ejRj8= +github.com/godoc-lint/godoc-lint v0.11.2 h1:Bp0FkJWoSdNsBikdNgIcgtaoo+xz6I/Y9s5WSBQUeeM= +github.com/godoc-lint/godoc-lint v0.11.2/go.mod h1:iVpGdL1JCikNH2gGeAn3Hh+AgN5Gx/I/cxV+91L41jo= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -287,12 +287,12 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.8.0 h1:wJnr3hJWY3eVzOUcfwbDc2qbi2RDEpvLmQeNFaPSNYA= -github.com/golangci/golangci-lint/v2 v2.8.0/go.mod h1:xl+HafQ9xoP8rzw0z5AwnO5kynxtb80e8u02Ej/47RI= -github.com/golangci/golines v0.14.0 h1:xt9d3RKBjhasA3qpoXs99J2xN2t6eBlpLHt0TrgyyXc= -github.com/golangci/golines v0.14.0/go.mod h1:gf555vPG2Ia7mmy2mzmhVQbVjuK8Orw0maR1G4vVAAQ= -github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= -github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/golangci-lint/v2 v2.10.1 h1:flhw5Px6ojbLyEFzXvJn5B2HEdkkRlkhE1SnmCbQBiE= +github.com/golangci/golangci-lint/v2 v2.10.1/go.mod h1:dBsrOk6zj0vDhlTv+IiJGqkDokR24IVTS7W3EVfPTQY= +github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0= +github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10= +github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg= +github.com/golangci/misspell v0.8.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= @@ -326,8 +326,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -471,8 +471,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.13.0 h1:yFbEVliCVKRXY8UgwEO7EOYNopvjb1BFbmYqm9hZjBM= -github.com/mgechev/revive v1.13.0/go.mod h1:efJfeBVCX2JUumNQ7dtOLDja+QKj9mYGgEZA7rt5u+0= +github.com/mgechev/revive v1.14.0 h1:CC2Ulb3kV7JFYt+izwORoS3VT/+Plb8BvslI/l1yZsc= +github.com/mgechev/revive v1.14.0/go.mod h1:MvnujelCZBZCaoDv5B3foPo6WWgULSSFxvfxp7GsPfo= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -496,14 +496,14 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= -github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= +github.com/nunnatsa/ginkgolinter v0.23.0 h1:x3o4DGYOWbBMP/VdNQKgSj+25aJKx2Pe6lHr8gBcgf8= +github.com/nunnatsa/ginkgolinter v0.23.0/go.mod h1:9qN1+0akwXEccwV1CAcCDfcoBlWXHB+ML9884pL4SZ4= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= -github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= -github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -539,8 +539,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -599,8 +597,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= -github.com/securego/gosec/v2 v2.22.11 h1:tW+weM/hCM/GX3iaCV91d5I6hqaRT2TPsFM1+USPXwg= -github.com/securego/gosec/v2 v2.22.11/go.mod h1:KE4MW/eH0GLWztkbt4/7XpyH0zJBBnu7sYB4l6Wn7Mw= +github.com/securego/gosec/v2 v2.23.0 h1:h4TtF64qFzvnkqvsHC/knT7YC5fqyOCItlVR8+ptEBo= +github.com/securego/gosec/v2 v2.23.0/go.mod h1:qRHEgXLFuYUDkI2T7W7NJAmOkxVhkR0x9xyHOIcMNZ0= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -608,8 +606,8 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= @@ -641,7 +639,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= @@ -696,8 +693,8 @@ go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= -go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= -go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= +go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50= +go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA= go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -717,8 +714,6 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= @@ -746,12 +741,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 h1:HDjDiATsGqvuqvkDvgJjD1IgPrVekcSXVVE21JwvzGE= -golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= +golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 h1:qWFG1Dj7TBjOjOvhEOkmyGPVoquqUKnIU0lEVLp8xyk= +golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -779,8 +774,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -819,8 +814,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -895,7 +890,6 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -903,16 +897,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -923,8 +917,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -978,8 +972,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= -golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1084,7 +1078,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1094,8 +1087,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= -honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= +honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= +honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= diff --git a/internal/commands/auth/file_storage.go b/internal/commands/auth/file_storage.go index 4a739e64..fe14e089 100644 --- a/internal/commands/auth/file_storage.go +++ b/internal/commands/auth/file_storage.go @@ -17,8 +17,10 @@ import ( // tokenFileData represents the structure of the credentials file type tokenFileData struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` + //nolint:gosec // G117: This struct is for internal credential storage + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + //nolint:gosec // G117: This struct is for internal credential storage RefreshToken string `json:"refresh_token,omitempty"` Expiry time.Time `json:"expiry,omitempty"` } diff --git a/internal/commands/auth/login_interactive_internal.go b/internal/commands/auth/login_interactive_internal.go index 7031cc2e..64423fa8 100644 --- a/internal/commands/auth/login_interactive_internal.go +++ b/internal/commands/auth/login_interactive_internal.go @@ -99,7 +99,8 @@ type DeviceCodeConfig struct { // ClientCredentialsConfig holds the configuration for client credentials authentication type ClientCredentialsConfig struct { - ClientID string + ClientID string + //nolint:gosec // G117: This struct is used to capture user input ClientSecret string EnvironmentID string RegionCode string diff --git a/internal/commands/auth/use_keychain_test.go b/internal/commands/auth/use_keychain_test.go index 453b58df..4e891435 100644 --- a/internal/commands/auth/use_keychain_test.go +++ b/internal/commands/auth/use_keychain_test.go @@ -126,7 +126,9 @@ func TestLoadTokenForMethod_WithKeychainDisabled(t *testing.T) { // Set file-storage to true to disable keychain t.Setenv("PINGCLI_LOGIN_STORAGE_TYPE", "file_system") + //nolint:gosec // Test tokens testToken := &oauth2.Token{ + //nolint:gosec // G101: Test tokens AccessToken: "test-load-access-token", TokenType: "Bearer", RefreshToken: "test-load-refresh-token", @@ -409,6 +411,7 @@ func TestEnvironmentVariable_FileStorage(t *testing.T) { // Reinitialize koanf to pick up environment variable testutils_koanf.InitKoanfs(t) + //nolint:gosec // G101: Test tokens testToken := &oauth2.Token{ AccessToken: "test-env-var-token", TokenType: "Bearer", diff --git a/internal/commands/license/license_internal.go b/internal/commands/license/license_internal.go index 22a756a4..f3971351 100644 --- a/internal/commands/license/license_internal.go +++ b/internal/commands/license/license_internal.go @@ -92,6 +92,7 @@ func runLicenseRequest(ctx context.Context, product, version, devopsUser, devops req.Header.Set("Version", version) client := &http.Client{} + //nolint:gosec // G704: Trusting configured URL res, err := client.Do(req) if err != nil { return licenseData, &errs.PingCLIError{Prefix: licenseErrorPrefix, Err: err} diff --git a/internal/commands/platform/export_internal_test.go b/internal/commands/platform/export_internal_test.go index 9b1212ae..efb1efa0 100644 --- a/internal/commands/platform/export_internal_test.go +++ b/internal/commands/platform/export_internal_test.go @@ -100,7 +100,7 @@ func Test_RunInternalExport(t *testing.T) { pfClientId: customtypes.StringPtr(""), expectedError: ErrClientCredentialsEmpty, }, - { + { //nolint:gosec // G101: Test credentials name: "Test invalid client credentials - PingFederate Client Credentials Auth", services: []string{customtypes.ENUM_EXPORT_SERVICE_PINGFEDERATE}, pfAuthType: customtypes.PingFederateAuthenticationType(customtypes.ENUM_PINGFEDERATE_AUTHENTICATION_TYPE_CLIENT_CREDENTIALS), diff --git a/internal/commands/request/request_internal_test.go b/internal/commands/request/request_internal_test.go index 6c443fd7..ae745587 100644 --- a/internal/commands/request/request_internal_test.go +++ b/internal/commands/request/request_internal_test.go @@ -27,7 +27,8 @@ func Test_RunInternalRequestWithFail(t *testing.T) { t.Fatal("This should never run due to internal request resulting in os.Exit(1)") } else { cmdName := os.Args[0] - cmd := exec.CommandContext(t.Context(), cmdName, "-test.run=Test_RunInternalRequestWithFail") //#nosec G204 -- This is a test + //nolint:gosec // G702, G204: Re-executing test binary + cmd := exec.CommandContext(t.Context(), cmdName, "-test.run=Test_RunInternalRequestWithFail") cmd.Env = append(os.Environ(), "RUN_INTERNAL_FAIL_TEST=true") err := cmd.Run() diff --git a/internal/commands/request/request_pingone.go b/internal/commands/request/request_pingone.go index a89dba3c..ffe5af34 100644 --- a/internal/commands/request/request_pingone.go +++ b/internal/commands/request/request_pingone.go @@ -129,6 +129,7 @@ func runInternalPingOneRequest(uri string) (err error) { req.Header.Add("Content-Type", "application/json") } + //nolint:gosec // G704: Generic request command res, err := client.Do(req) if err != nil { return err diff --git a/internal/input/input.go b/internal/input/input.go index 07be6616..84662fff 100644 --- a/internal/input/input.go +++ b/internal/input/input.go @@ -24,8 +24,10 @@ var ( func RunPromptSecret(message string, validateFunc func(string) error, rc io.ReadCloser) (string, error) { // Prefer terminal password read to avoid any UI redraws. for { + //nolint:gosec // G115: Fd() returns uintptr but fits in int for stdin if term.IsTerminal(int(os.Stdin.Fd())) { fmt.Printf("%s: ", message) + //nolint:gosec // G115: Fd() returns uintptr but fits in int for stdin bytes, err := term.ReadPassword(int(os.Stdin.Fd())) fmt.Println() if err != nil { diff --git a/internal/logger/logger.go b/internal/logger/logger.go index b8b74a93..5e0e2e3d 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -54,6 +54,7 @@ func Get() zerolog.Logger { if logPathEnv != "" && logLevel != zerolog.Disabled { var err error logPathEnv = filepath.Clean(logPathEnv) + //nolint:gosec // G703: Path provided by user via env var is trusted output, err = os.Create(logPathEnv) if err != nil { // Most likely the directory specified for the log path does not exist diff --git a/internal/testing/testutils_resource/pingone_mfa_testable_resources/mfa_application_push_credential.go b/internal/testing/testutils_resource/pingone_mfa_testable_resources/mfa_application_push_credential.go index 22569406..74c5a738 100644 --- a/internal/testing/testutils_resource/pingone_mfa_testable_resources/mfa_application_push_credential.go +++ b/internal/testing/testutils_resource/pingone_mfa_testable_resources/mfa_application_push_credential.go @@ -40,7 +40,7 @@ func createMfaApplicationPushCredential(t *testing.T, clientInfo *connector.Clie request := clientInfo.PingOneApiClient.MFAAPIClient.ApplicationsApplicationMFAPushCredentialsApi.CreateMFAPushCredential(clientInfo.PingOneContext, clientInfo.PingOneExportEnvironmentID, applicationId) clientStruct := mfa.MFAPushCredentialRequest{ - MFAPushCredentialHMS: &mfa.MFAPushCredentialHMS{ + MFAPushCredentialHMS: &mfa.MFAPushCredentialHMS{ //nolint:gosec // G101: Test credentials Type: mfa.ENUMMFAPUSHCREDENTIALATTRTYPE_HMS, ClientId: "897389789432", ClientSecret: "B23897498", diff --git a/internal/testing/testutils_resource/pingone_sso_testable_resources/identity_provider.go b/internal/testing/testutils_resource/pingone_sso_testable_resources/identity_provider.go index 9243c43a..92a6829d 100644 --- a/internal/testing/testutils_resource/pingone_sso_testable_resources/identity_provider.go +++ b/internal/testing/testutils_resource/pingone_sso_testable_resources/identity_provider.go @@ -36,6 +36,7 @@ func createIdentityProvider(t *testing.T, clientInfo *connector.ClientInfo, reso } request := clientInfo.PingOneApiClient.ManagementAPIClient.IdentityProvidersApi.CreateIdentityProvider(clientInfo.PingOneContext, clientInfo.PingOneExportEnvironmentID) + //nolint:gosec // G101: Test credentials clientStruct := management.IdentityProvider{ IdentityProviderOIDC: &management.IdentityProviderOIDC{ AuthorizationEndpoint: "https://example.com/auth", diff --git a/internal/testing/testutils_terraform/terraform_utils.go b/internal/testing/testutils_terraform/terraform_utils.go index 83daa94b..00198b9a 100644 --- a/internal/testing/testutils_terraform/terraform_utils.go +++ b/internal/testing/testutils_terraform/terraform_utils.go @@ -182,6 +182,7 @@ provider "pingone" { // Write main.tf to testing directory mainTFFilepath := filepath.Join(exportDir, "main.tf") + //nolint:gosec // G703: Test utility file path if err := os.WriteFile(mainTFFilepath, []byte(mainTFFileContents), 0600); err != nil { t.Fatalf("Failed to write main.tf to testing directory: %v", err) } diff --git a/tools/generate-options-docs/docgen/docgen.go b/tools/generate-options-docs/docgen/docgen.go index eb625e87..2a07a753 100644 --- a/tools/generate-options-docs/docgen/docgen.go +++ b/tools/generate-options-docs/docgen/docgen.go @@ -63,7 +63,7 @@ func GenerateMarkdown() string { for _, category := range cats { properties := propertyCategoryInformation[category] slices.Sort(properties) - outputBuilder.WriteString(fmt.Sprintf("#### %s Properties\n\n", category)) + fmt.Fprintf(&outputBuilder, "#### %s Properties\n\n", category) outputBuilder.WriteString("| Config File Property | Equivalent Parameter | Environment Variable | Type | Purpose |\n") outputBuilder.WriteString("|---|---|---|---|---|\n") for _, property := range properties { @@ -109,8 +109,8 @@ func GenerateAsciiDocWithDates(created, revdate string) string { } var b strings.Builder b.WriteString("= Configuration Settings Reference\n") - b.WriteString(fmt.Sprintf(":created-date: %s\n", created)) - b.WriteString(fmt.Sprintf(":revdate: %s\n", revdate)) + fmt.Fprintf(&b, ":created-date: %s\n", created) + fmt.Fprintf(&b, ":revdate: %s\n", revdate) b.WriteString(":resourceid: pingcli_configuration_settings_reference\n\n") b.WriteString("The following configuration settings can be applied when using Ping CLI.\n\n") b.WriteString("The following configuration settings can be applied by using the xref:command_reference:pingcli_config_set.adoc[`config set` command] to persist the configuration value for a given **Configuration Key** in the Ping CLI configuration file.\n\n") @@ -152,7 +152,7 @@ func GenerateAsciiDocWithDates(created, revdate string) string { eqParam := asciiDocEquivalentParameter(opt) envVar := opt.EnvVar purpose := sanitizeUsage(opt) - b.WriteString(fmt.Sprintf("| `%s` | %s | %s | %s | %s\n", key, eqParam, formatEnvVar(envVar), dataType, purpose)) + fmt.Fprintf(&b, "| `%s` | %s | %s | %s | %s\n", key, eqParam, formatEnvVar(envVar), dataType, purpose) } b.WriteString("|===\n\n") } From 95ce0703f544bac0b5fcc9b65ff9c19e8308bdcc Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Wed, 18 Feb 2026 16:47:43 -0500 Subject: [PATCH 7/8] update changelog entry, sanitize config file inputs --- .changelog/pr-157.txt | 2 +- cmd/root.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.changelog/pr-157.txt b/.changelog/pr-157.txt index a2b0c585..afbd4e85 100644 --- a/.changelog/pr-157.txt +++ b/.changelog/pr-157.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -code refactor for storage logic and duplication +fix issue where stale tokens were not removed from keychain, storage logic refactor ``` diff --git a/cmd/root.go b/cmd/root.go index bb108b94..54e39e86 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -173,6 +173,9 @@ func ParseArgsForConfigFile(args []string) string { } func checkCfgFileLocation(cfgFile string) { + // Clean the path to remove potential path traversal issues before using it + cfgFile = filepath.Clean(cfgFile) + // Check existence of configuration file //nolint:gosec // G703: Path provided by user via flag is trusted _, err := os.Stat(cfgFile) @@ -191,6 +194,9 @@ func checkCfgFileLocation(cfgFile string) { } func createConfigFile(cfgFile string) { + // Clean the path to remove potential path traversal issues before using it + cfgFile = filepath.Clean(cfgFile) + output.Message(fmt.Sprintf("Creating new Ping CLI configuration file at: %s", cfgFile), nil) // MkdirAll does nothing if directories already exist. Create needed directories for config file location. @@ -213,7 +219,7 @@ func createConfigFile(cfgFile string) { err = tempKoanf.WriteFile() if err != nil { - output.SystemError(fmt.Sprintf("Failed to create new configuration file '%s': %v", cfgFile, err), nil) + output.SystemError(fmt.Sprintf("Failed to write to new configuration file '%s': %v", cfgFile, err), nil) } } From aab8ba3cb7c8f54878e681af18bdc5d6a2b26d0b Mon Sep 17 00:00:00 2001 From: wesleymccollam Date: Wed, 18 Feb 2026 17:47:42 -0500 Subject: [PATCH 8/8] use go.mod version for golangci-lint tool --- .../workflows/code-analysis-lint-test.yaml | 5 +- go.mod | 49 ++++---- go.sum | 119 +++++++++--------- 3 files changed, 92 insertions(+), 81 deletions(-) diff --git a/.github/workflows/code-analysis-lint-test.yaml b/.github/workflows/code-analysis-lint-test.yaml index bfb445b2..3963b8f0 100644 --- a/.github/workflows/code-analysis-lint-test.yaml +++ b/.github/workflows/code-analysis-lint-test.yaml @@ -75,13 +75,16 @@ jobs: with: go-version-file: "go.mod" cache: true + - id: golangci-lint-version + run: >- + echo "version=$(go tool golangci-lint version --format short)" >> $GITHUB_OUTPUT - name: golangci-lint uses: golangci/golangci-lint-action@v8 with: # Require: The version of golangci-lint to use. # When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version. # When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit. - version: latest + version: "${{ steps.golangci-lint-version.outputs.version }}" # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/go.mod b/go.mod index 0c1d16fc..b447152a 100644 --- a/go.mod +++ b/go.mod @@ -28,9 +28,9 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 - golang.org/x/mod v0.33.0 + golang.org/x/mod v0.31.0 golang.org/x/oauth2 v0.33.0 - golang.org/x/term v0.40.0 + golang.org/x/term v0.38.0 google.golang.org/grpc v1.76.0 google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 @@ -54,12 +54,12 @@ require ( github.com/BurntSushi/toml v1.6.0 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/MirrexOne/unqueryvet v1.5.3 // indirect + github.com/MirrexOne/unqueryvet v1.4.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.23.1 // indirect + github.com/alecthomas/chroma/v2 v2.21.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect - github.com/alexkohler/prealloc v1.0.2 // indirect + github.com/alexkohler/prealloc v1.0.1 // indirect github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect @@ -70,7 +70,7 @@ require ( github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v4 v4.7.0 // indirect - github.com/bombsimon/wsl/v5 v5.6.0 // indirect + github.com/bombsimon/wsl/v5 v5.3.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect github.com/butuzov/ireturn v0.4.0 // indirect @@ -81,7 +81,7 @@ require ( github.com/charithe/durationcheck v0.0.11 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/chzyer/readline v1.5.1 // indirect @@ -98,7 +98,7 @@ require ( github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.20 // indirect + github.com/ghostiam/protogetter v0.3.18 // indirect github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect @@ -107,20 +107,20 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/godoc-lint/godoc-lint v0.11.2 // indirect + github.com/godoc-lint/godoc-lint v0.11.1 // indirect github.com/gofrs/flock v0.13.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint/v2 v2.10.1 // indirect - github.com/golangci/golines v0.15.0 // indirect - github.com/golangci/misspell v0.8.0 // indirect + github.com/golangci/golangci-lint/v2 v2.8.0 // indirect + github.com/golangci/golines v0.14.0 // indirect + github.com/golangci/misspell v0.7.0 // indirect github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect @@ -167,7 +167,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.14.0 // indirect + github.com/mgechev/revive v1.13.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -176,7 +176,7 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.23.0 // indirect + github.com/nunnatsa/ginkgolinter v0.21.2 // indirect github.com/oklog/run v1.2.0 // indirect github.com/patrickcping/pingone-go-sdk-v2/credentials v0.12.0 // indirect github.com/patrickcping/pingone-go-sdk-v2/verify v0.10.0 // indirect @@ -202,8 +202,8 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/securego/gosec/v2 v2.23.0 // indirect - github.com/sirupsen/logrus v1.9.4 // indirect + github.com/securego/gosec/v2 v2.22.11 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -233,19 +233,20 @@ require ( gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.14.0 // indirect go-simpler.org/sloglint v0.11.1 // indirect - go.augendre.info/arangolint v0.4.0 // indirect + go.augendre.info/arangolint v0.3.1 // indirect go.augendre.info/fatcontext v0.9.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect - golang.org/x/net v0.50.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/net v0.48.0 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/text v0.34.0 // indirect - golang.org/x/tools v0.42.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect + golang.org/x/tools v0.40.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect - honnef.co/go/tools v0.7.0 // indirect + honnef.co/go/tools v0.6.1 // indirect mvdan.cc/gofumpt v0.9.2 // indirect mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect ) diff --git a/go.sum b/go.sum index bf99b75b..06f64bd7 100644 --- a/go.sum +++ b/go.sum @@ -67,14 +67,14 @@ github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/MirrexOne/unqueryvet v1.5.3 h1:LpT3rsH+IY3cQddWF9bg4C7jsbASdGnrOSofY8IPEiw= -github.com/MirrexOne/unqueryvet v1.5.3/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU= +github.com/MirrexOne/unqueryvet v1.4.0 h1:6KAkqqW2KUnkl9Z0VuTphC3IXRPoFqEkJEtyxxHj5eQ= +github.com/MirrexOne/unqueryvet v1.4.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= -github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= +github.com/alecthomas/chroma/v2 v2.21.1 h1:FaSDrp6N+3pphkNKU6HPCiYLgm8dbe5UXIXcoBhZSWA= +github.com/alecthomas/chroma/v2 v2.21.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= @@ -86,8 +86,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= -github.com/alexkohler/prealloc v1.0.2 h1:MPo8cIkGkZytq7WNH9UHv3DIX1mPz1RatPXnZb0zHWQ= -github.com/alexkohler/prealloc v1.0.2/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= +github.com/alexkohler/prealloc v1.0.1 h1:A9P1haqowqUxWvU9nk6tQ7YktXIHf+LQM9wPRhuteEE= +github.com/alexkohler/prealloc v1.0.1/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -110,8 +110,8 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= -github.com/bombsimon/wsl/v5 v5.6.0 h1:4z+/sBqC5vUmSp1O0mS+czxwH9+LKXtCWtHH9rZGQL8= -github.com/bombsimon/wsl/v5 v5.6.0/go.mod h1:Uqt2EfrMj2NV8UGoN1f1Y3m0NpUVCsUdrNCdet+8LvU= +github.com/bombsimon/wsl/v5 v5.3.0 h1:nZWREJFL6U3vgW/B1lfDOigl+tEF6qgs6dGGbFeR0UM= +github.com/bombsimon/wsl/v5 v5.3.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= @@ -137,8 +137,8 @@ github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4p github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= -github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= @@ -195,8 +195,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.20 h1:oW7OPFit2FxZOpmMRPP9FffU4uUpfeE/rEdE1f+MzD0= -github.com/ghostiam/protogetter v0.3.20/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= +github.com/ghostiam/protogetter v0.3.18 h1:yEpghRGtP9PjKvVXtEzGpYfQj1Wl/ZehAfU6fr62Lfo= +github.com/ghostiam/protogetter v0.3.18/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog= github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -236,8 +236,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= -github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -245,8 +245,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godoc-lint/godoc-lint v0.11.2 h1:Bp0FkJWoSdNsBikdNgIcgtaoo+xz6I/Y9s5WSBQUeeM= -github.com/godoc-lint/godoc-lint v0.11.2/go.mod h1:iVpGdL1JCikNH2gGeAn3Hh+AgN5Gx/I/cxV+91L41jo= +github.com/godoc-lint/godoc-lint v0.11.1 h1:z9as8Qjiy6miRIa3VRymTa+Gt2RLnGICVikcvlUVOaA= +github.com/godoc-lint/godoc-lint v0.11.1/go.mod h1:BAqayheFSuZrEAqCRxgw9MyvsM+S/hZwJbU1s/ejRj8= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -287,12 +287,12 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.10.1 h1:flhw5Px6ojbLyEFzXvJn5B2HEdkkRlkhE1SnmCbQBiE= -github.com/golangci/golangci-lint/v2 v2.10.1/go.mod h1:dBsrOk6zj0vDhlTv+IiJGqkDokR24IVTS7W3EVfPTQY= -github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0= -github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10= -github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg= -github.com/golangci/misspell v0.8.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/golangci-lint/v2 v2.8.0 h1:wJnr3hJWY3eVzOUcfwbDc2qbi2RDEpvLmQeNFaPSNYA= +github.com/golangci/golangci-lint/v2 v2.8.0/go.mod h1:xl+HafQ9xoP8rzw0z5AwnO5kynxtb80e8u02Ej/47RI= +github.com/golangci/golines v0.14.0 h1:xt9d3RKBjhasA3qpoXs99J2xN2t6eBlpLHt0TrgyyXc= +github.com/golangci/golines v0.14.0/go.mod h1:gf555vPG2Ia7mmy2mzmhVQbVjuK8Orw0maR1G4vVAAQ= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= @@ -326,8 +326,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= -github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -471,8 +471,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.14.0 h1:CC2Ulb3kV7JFYt+izwORoS3VT/+Plb8BvslI/l1yZsc= -github.com/mgechev/revive v1.14.0/go.mod h1:MvnujelCZBZCaoDv5B3foPo6WWgULSSFxvfxp7GsPfo= +github.com/mgechev/revive v1.13.0 h1:yFbEVliCVKRXY8UgwEO7EOYNopvjb1BFbmYqm9hZjBM= +github.com/mgechev/revive v1.13.0/go.mod h1:efJfeBVCX2JUumNQ7dtOLDja+QKj9mYGgEZA7rt5u+0= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -496,14 +496,14 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.23.0 h1:x3o4DGYOWbBMP/VdNQKgSj+25aJKx2Pe6lHr8gBcgf8= -github.com/nunnatsa/ginkgolinter v0.23.0/go.mod h1:9qN1+0akwXEccwV1CAcCDfcoBlWXHB+ML9884pL4SZ4= +github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= +github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= -github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= -github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= -github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -539,6 +539,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -597,8 +599,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= -github.com/securego/gosec/v2 v2.23.0 h1:h4TtF64qFzvnkqvsHC/knT7YC5fqyOCItlVR8+ptEBo= -github.com/securego/gosec/v2 v2.23.0/go.mod h1:qRHEgXLFuYUDkI2T7W7NJAmOkxVhkR0x9xyHOIcMNZ0= +github.com/securego/gosec/v2 v2.22.11 h1:tW+weM/hCM/GX3iaCV91d5I6hqaRT2TPsFM1+USPXwg= +github.com/securego/gosec/v2 v2.22.11/go.mod h1:KE4MW/eH0GLWztkbt4/7XpyH0zJBBnu7sYB4l6Wn7Mw= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -606,8 +608,8 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= @@ -639,6 +641,7 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= @@ -693,8 +696,8 @@ go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= -go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50= -go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA= +go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= +go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -714,6 +717,8 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= @@ -741,12 +746,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 h1:qWFG1Dj7TBjOjOvhEOkmyGPVoquqUKnIU0lEVLp8xyk= -golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 h1:HDjDiATsGqvuqvkDvgJjD1IgPrVekcSXVVE21JwvzGE= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -774,8 +779,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -814,8 +819,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -890,6 +895,7 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -897,16 +903,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -917,8 +923,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -972,8 +978,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -1078,6 +1084,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1087,8 +1094,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= -honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= +honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= +honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI=