Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Oct 17, 2025

what

This pull request introduces the atmos auth logout command, enabling users to securely remove locally cached credentials. The command supports:

  • Identity-specific logout: Removes credentials for a given identity and its entire authentication chain.
  • Provider-specific logout: Removes all credentials associated with a particular provider.
  • Interactive mode: Prompts the user to select what to logout when no arguments are provided.
  • Dry-run mode: Previews what would be removed without making changes.
  • Comprehensive cleanup: Deletes credentials from the system keyring and provider-specific files (e.g., AWS credentials).
  • Best-effort error handling: Continues cleanup even if individual steps fail, reporting all encountered errors.

why

This feature addresses several key pain points:

  • Security: Allows users to securely remove stale credentials, reducing the risk of unauthorized access.
  • Developer Experience: Simplifies switching between different identities or environments by providing a clean way to remove existing credentials.
  • Compliance: Enables auditing of credential removal and ensures adherence to security policies.
  • Troubleshooting: Provides a straightforward method to clear authentication caches when debugging.

The implementation uses native Go operations for file system cleanup and integrates with go-keyring for cross-platform credential store access. It leverages Charmbracelet libraries for a polished interactive user experience and styled output.

references

closes #735

Summary by CodeRabbit

Release Notes

  • New Features

    • Added atmos auth logout CLI command to remove stored credentials
    • Supports logout by identity, by provider, or all identities at once
    • Interactive mode to select which credentials to remove
    • Dry-run mode to preview credential removals without executing
    • Browser session warning displayed after successful logout
  • Documentation

    • Added guides and reference documentation for logout workflows and usage

@osterman osterman requested a review from a team as a code owner October 17, 2025 19:39
@github-actions github-actions bot added the size/xl Extra large size PR label Oct 17, 2025
@mergify
Copy link

mergify bot commented Oct 17, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 17, 2025

Warning

Rate limit exceeded

@osterman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 11 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cba7fe8 and 8ac86aa.

📒 Files selected for processing (3)
  • .golangci.yml (1 hunks)
  • pkg/config/homedir/homedir_test.go (3 hunks)
  • website/blog/2025-10-17-auth-logout-feature.md (1 hunks)
📝 Walkthrough

Walkthrough

Introduces comprehensive auth logout functionality for Atmos, including a new CLI command (atmos auth logout) with interactive and provider/identity-specific logout flows, AWS credential file cleanup capabilities, interface extensions for logout operations across all auth components (providers, identities, manager), new error types, and extensive test coverage.

Changes

Cohort / File(s) Summary
CLI Logout Command
cmd/auth_logout.go, cmd/auth_logout_test.go, cmd/cmd_utils.go
New Cobra-based logout subcommand with identity/provider-specific flows, interactive mode via huh UI, dry-run support, browser session warnings, and argument validation; includes shell completion for identity positional arguments.
Error Definitions
errors/errors.go
Adds 10 new logout-related error variables: ErrLogoutFailed, ErrPartialLogout, ErrLogoutNotSupported, ErrLogoutNotImplemented, ErrKeyringDeletion, ErrProviderLogout, ErrIdentityLogout, ErrIdentityNotInConfig, ErrProviderNotInConfig, ErrInvalidLogoutOption.
Auth Interfaces & Types
pkg/auth/types/interfaces.go, pkg/auth/types/mock_interfaces.go
Extends Provider, Identity, and AuthManager interfaces with Logout and GetFilesDisplayPath methods; generates comprehensive gomock mocks for all interfaces.
Auth Manager Logout Logic
pkg/auth/manager.go, pkg/auth/manager_logout_test.go, pkg/auth/manager_test.go
Implements manager-level logout orchestration: Logout, LogoutProvider, LogoutAll methods with keyring deletion, provider cleanup, transitive chain resolution, error aggregation, and partial failure handling.
AWS File Management
pkg/auth/cloud/aws/files.go, pkg/auth/cloud/aws/files_test.go, pkg/auth/cloud/aws/files_logout_test.go, pkg/auth/cloud/aws/spec.go, pkg/auth/cloud/aws/spec_test.go
Adds configurable basePath parameter, CleanupIdentity for removing identity-specific credentials, CleanupAll for complete directory removal, GetBaseDir/GetDisplayPath accessors, and spec validation for files.base_path configuration.
AWS Setup Updates
pkg/auth/cloud/aws/setup.go, pkg/auth/cloud/aws/setup_test.go, pkg/auth/cloud/aws/env.go
Adds basePath parameter to SetupFiles and SetEnvironmentVariables; modifies LoadIsolatedAWSConfig to disable shared AWS config files.
AWS Provider Logout
pkg/auth/providers/aws/saml.go, pkg/auth/providers/aws/saml_test.go, pkg/auth/providers/aws/sso.go, pkg/auth/providers/aws/sso_test.go, pkg/auth/providers/aws/logout_test_helpers.go
Implements Logout and GetFilesDisplayPath on SAML and SSO providers with file cleanup and display path retrieval.
GitHub Provider Logout
pkg/auth/providers/github/oidc.go, pkg/auth/providers/github/oidc_test.go
Adds no-op Logout (returns ErrLogoutNotSupported) and empty GetFilesDisplayPath on OIDC provider.
AWS Identity Logout
pkg/auth/identities/aws/assume_role.go, pkg/auth/identities/aws/assume_role_test.go, pkg/auth/identities/aws/permission_set.go, pkg/auth/identities/aws/permission_set_test.go, pkg/auth/identities/aws/user.go, pkg/auth/identities/aws/user_test.go
Adds Logout method to assume-role, permission-set, and user identities; user identity performs CleanupIdentity for credential file cleanup.
Credentials Store
pkg/auth/credentials/store.go, pkg/auth/credentials/store_test.go
Enables error unwrapping via %w formatting; treats keyring.ErrNotFound as success in Delete (idempotent); adds keyring-backed store tests.
Auth Hooks & Config
pkg/auth/hooks_test.go, pkg/config/cache.go
Stub auth manager methods extended for logout; BrowserSessionWarningShown field added to CacheConfig.
Documentation
docs/prd/auth-logout.md, website/blog/2025-10-17-auth-logout-feature.md, website/docs/cli/commands/auth/logout.mdx, website/docs/cli/commands/auth/auth-user-configure.mdx
Product requirements document, blog post, and CLI documentation detailing logout workflows, error handling, security considerations, and usage examples.
Test & Build Infrastructure
tests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.golden, internal/exec/describe_config_test.go, internal/exec/describe_stacks_test.go, internal/exec/version_test.go, pkg/git/mock_interface.go, pkg/config/homedir/homedir_test.go, .gitignore, NOTICE
Updates test snapshots for new logout subcommand; reorders imports; updates git mock to use v5 Repository; adds homedir cache reset tests; ignores merge artifacts; adds dependency licenses.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CLI Command
    participant Manager as AuthManager
    participant KS as CredentialStore
    participant Provider
    participant Identity
    participant Files as File Manager

    User->>CLI: atmos auth logout [identity]
    
    alt Identity-specific logout
        CLI->>Manager: Logout(ctx, identityName)
        Manager->>Manager: resolveProviderForIdentity(identityName)
        
        loop For each credential in chain
            Manager->>KS: Delete(alias)
        end
        
        Manager->>Identity: Logout(ctx)
        alt Identity cleanup
            Identity->>Files: CleanupIdentity(provider, identity)
            Files->>Files: Remove INI sections
        end
        
        Manager->>Provider: Logout(ctx)
        alt Provider cleanup
            Provider->>Files: Cleanup(provider)
            Files->>Files: Remove credential files
        end
        
        Manager-->>CLI: Success or ErrPartialLogout
    else Provider-specific logout
        CLI->>Manager: LogoutProvider(ctx, providerName)
        Manager->>Manager: Get all identities for provider
        
        loop For each identity
            Manager->>Manager: Logout(ctx, identityName)
        end
        
        Manager->>Provider: Logout(ctx)
        Manager-->>CLI: Result
    else All identities
        CLI->>Manager: LogoutAll(ctx)
        Manager->>Manager: Get all providers
        
        loop For each provider
            Manager->>Manager: LogoutProvider(ctx, providerName)
        end
        
        Manager-->>CLI: Aggregated results
    end
    
    alt Dry-run mode
        CLI->>CLI: Display cleanup plan
    else Browser warning
        CLI->>CLI: Show browser session notice
    end
    
    CLI-->>User: Display results / errors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

This PR involves substantial, multi-faceted changes across the auth system. Key complexity drivers:

  • Interface extensions: Seven new methods added to Provider, Identity, and AuthManager interfaces requiring implementations across five provider/identity types.
  • Orchestration logic: Manager-level logout with chain resolution, transitive cleanup, partial failure handling, and error aggregation.
  • File system operations: New AWS file cleanup (CleanupIdentity, CleanupAll) with INI parsing/writing and cross-platform path handling.
  • Heterogeneous changes: Logout logic varies per provider (AWS SAML/SSO have file cleanup, GitHub OIDC is unsupported), creating distinct reasoning paths.
  • Test density: Comprehensive test coverage across manager, providers, identities, file operations, and credential store with mock expectations.
  • Error handling: New error types and partial-failure semantics requiring careful review of propagation.

Possibly related PRs

Suggested reviewers

  • aknysh
  • mcalhoun

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning There is a critical mismatch between the pull request implementation and the linked issue #735. The PR implements the atmos auth logout command with features like identity-specific logout, provider-specific logout, interactive mode, and dry-run functionality. However, issue #735 requires making the atmos version command work when configuration is broken or corrupted. The PR does not address any of the stated objectives from issue #735: it does not provide resilience for the version command when parsing configuration, does not preserve error behavior for other commands, and does not include utilities to detect version command execution. The PR is entirely focused on logout functionality, which is orthogonal to the version command resilience requirements. Verify that the correct issue is linked or that the PR objectives have been mislabeled. If this PR is intended to address issue #735, substantial rework would be needed to implement version command resilience instead of logout functionality. If the logout feature is the intended deliverable, link this PR to the appropriate issue (such as the one referenced in the PR objectives, which appears to be DEV-3705 based on the branch name).
Out of Scope Changes Check ⚠️ Warning The entire logout feature implementation—including cmd/auth_logout.go, new logout error definitions, AWS file cleanup methods (CleanupIdentity, CleanupAll), logout methods on identity and provider types, manager logout workflows (Logout, LogoutProvider, LogoutAll), comprehensive test suites for logout flows, and associated documentation—is out of scope for issue #735, which requires version command resilience when configuration is broken. While minor changes to version_test.go and other tangential files appear, they do not implement the core requirements from the linked issue. The PR lacks any implementation addressing configuration error handling for the version command or utilities for command detection. Either correct the linked issue reference to match the logout feature being implemented, or refactor the PR to address the stated objectives from issue #735 (version command resilience with broken configs). Mixing unrelated features under a single linked issue creates confusion and prevents proper tracking of feature completion.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Add auth logout command" directly and clearly identifies the primary change in the changeset. The extensive modifications across the codebase—including cmd/auth_logout.go, new logout-related error types, identity and provider logout methods, manager logout workflows, and comprehensive documentation—all center on implementing the auth logout feature. The title is specific and concise, allowing reviewers to quickly understand the main objective without ambiguity.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (25)
pkg/auth/identities/aws/permission_set.go (1)

267-274: Missing performance tracking call.

Per coding guidelines, add defer perf.Track() to all public functions. This applies to the new Logout method.

Apply this diff:

 // Logout removes identity-specific credential storage.
 func (i *permissionSetIdentity) Logout(ctx context.Context) error {
+	defer perf.Track()
+
 	// AWS permission-set identities don't have identity-specific storage.
 	// File cleanup is handled by the provider's Logout method.
 	// Keyring cleanup is handled by AuthManager.
 	log.Debug("Logout called for permission-set identity (no identity-specific cleanup)", "identity", i.name)
 	return nil
 }

Note: You'll need to import the perf package if not already present.

Based on coding guidelines

pkg/auth/identities/aws/assume_role.go (1)

278-285: Missing performance tracking call.

Per coding guidelines, add defer perf.Track() to all public functions.

Apply this diff:

 // Logout removes identity-specific credential storage.
 func (i *assumeRoleIdentity) Logout(ctx context.Context) error {
+	defer perf.Track()
+
 	// AWS assume-role identities don't have identity-specific storage.
 	// File cleanup is handled by the provider's Logout method.
 	// Keyring cleanup is handled by AuthManager.
 	log.Debug("Logout called for assume-role identity (no identity-specific cleanup)", "identity", i.name)
 	return nil
 }

Based on coding guidelines

pkg/auth/providers/aws/saml.go (1)

373-387: Missing performance tracking call.

Per coding guidelines, add defer perf.Track() to all public functions. Also consider passing ctx to track if needed.

Apply this diff:

 // Logout removes provider-specific credential storage.
 func (p *samlProvider) Logout(ctx context.Context) error {
+	defer perf.Track()
+
 	fileManager, err := awsCloud.NewAWSFileManager()
 	if err != nil {
 		return errors.Join(errUtils.ErrLogoutFailed, err)
 	}
 
 	if err := fileManager.Cleanup(p.name); err != nil {
 		log.Debug("Failed to cleanup AWS files for SAML provider", "provider", p.name, "error", err)
 		return errors.Join(errUtils.ErrLogoutFailed, err)
 	}
 
 	log.Debug("Cleaned up AWS files for SAML provider", "provider", p.name)
 	return nil
 }

Based on coding guidelines

pkg/auth/cloud/aws/files.go (2)

192-206: Missing performance tracking call.

Per coding guidelines, add defer perf.Track() to all public functions.

Apply this diff:

 // Cleanup removes AWS files for the provider.
 func (m *AWSFileManager) Cleanup(providerName string) error {
+	defer perf.Track()
+
 	providerDir := filepath.Join(m.baseDir, providerName)
 
 	if err := os.RemoveAll(providerDir); err != nil {
 		// If directory doesn't exist, that's not an error (already cleaned up).
 		if os.IsNotExist(err) {
 			return nil
 		}
 		errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, providerDir, "failed to cleanup AWS files")
 		return ErrCleanupAWSFiles
 	}
 
 	return nil
 }

Based on coding guidelines


208-220: Missing performance tracking call.

Per coding guidelines, add defer perf.Track() to all public functions.

Apply this diff:

 // CleanupAll removes entire ~/.aws/atmos directory.
 func (m *AWSFileManager) CleanupAll() error {
+	defer perf.Track()
+
 	if err := os.RemoveAll(m.baseDir); err != nil {
 		// If directory doesn't exist, that's not an error (already cleaned up).
 		if os.IsNotExist(err) {
 			return nil
 		}
 		errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, m.baseDir, "failed to cleanup all AWS files")
 		return ErrCleanupAWSFiles
 	}
 
 	return nil
 }

Based on coding guidelines

website/blog/2025-10-17-auth-logout-feature.md (7)

40-58: Add language identifier to fenced code block.

Code blocks should specify a language for proper syntax highlighting.

Apply this diff:

 **Example output:**
 
-```
+```text
 Logging out from identity: dev-admin

As per coding guidelines


67-74: Add language identifier to fenced code block.

Apply this diff:

 When run without arguments for an interactive experience:
 
-```
+```text
 ? Choose what to logout from:

As per coding guidelines


88-99: Add language identifier to fenced code block.

Apply this diff:

 This removes the provider credentials and all identities that authenticate through it:
 
-```
+```text
 Logging out from provider: aws-sso

As per coding guidelines


109-120: Add language identifier to fenced code block.

Apply this diff:

 Preview what would be removed without actually deleting anything:
 
-```
+```text
 Dry run mode: No credentials will be removed

As per coding guidelines


128-135: Add language identifier to fenced code block.

Apply this diff:

 Atmos intelligently resolves the complete authentication chain for your identity and removes credentials at each step:
 
-```
+```text
 aws-sso → dev-org-admin → dev-admin
    ↓           ↓              ↓
 Removed     Removed        Removed

As per coding guidelines


149-164: Add language identifier to fenced code block.

Apply this diff:

 The logout command continues even if individual steps fail, ensuring maximum cleanup:
 
-```
+```text
 Logging out from identity: dev-admin

As per coding guidelines


209-214: Add language identifier to fenced code block.

Apply this diff:

 All logout operations are logged for security auditing:
 
-```
+```text
 2025-10-17T10:15:30Z DEBUG Starting logout identity=dev-admin

As per coding guidelines

pkg/auth/manager.go (3)

756-763: Call Identity.Logout for every identity in the chain, not just the target.

Only the target identity’s Logout is invoked. Intermediate identities may have provider/identity-specific artifacts to clean.

Apply this diff to replace the single call with chain-wide best‑effort cleanup:

-    // Step 3: Call identity-specific cleanup.
-    if identity, exists := m.identities[identityName]; exists {
-        if err := identity.Logout(ctx); err != nil {
-            log.Debug("Identity logout failed", "identity", identityName, "error", err)
-            errs = append(errs, errors.Join(errUtils.ErrIdentityLogout, fmt.Errorf("identity %q: %v", identityName, err)))
-        }
-    }
+    // Step 3: Call identity-specific cleanup for all identities in the chain (skip provider element at index 0).
+    for i := 1; i < len(chain); i++ {
+        step := chain[i]
+        if identity, exists := m.identities[step]; exists {
+            if err := identity.Logout(ctx); err != nil {
+                log.Debug("Identity logout failed", "identity", step, "error", err)
+                errs = append(errs, errors.Join(errUtils.ErrIdentityLogout, fmt.Errorf("identity %q: %v", step, err)))
+            } else {
+                log.Debug("Identity logout successful", "identity", step)
+            }
+        }
+    }

800-831: Propagate partial‑success semantics in LogoutProvider.

Current logic returns ErrLogoutFailed if any error occurs, even if some deletions succeed. Match PRD: return ErrPartialLogout when at least one operation succeeds.

Apply this diff:

-    var errs []error
+    var errs []error
+    succeeded := 0
...
-    for _, identityName := range identityNames {
-        if err := m.Logout(ctx, identityName); err != nil {
+    for _, identityName := range identityNames {
+        if err := m.Logout(ctx, identityName); err != nil {
             log.Debug("Failed to logout identity", "identity", identityName, "error", err)
             errs = append(errs, errors.Join(errUtils.ErrIdentityLogout, fmt.Errorf("identity %q: %v", identityName, err)))
-        }
+            if errors.Is(err, errUtils.ErrPartialLogout) {
+                succeeded++
+            }
+        } else {
+            succeeded++
+        }
     }
...
-    if err := m.credentialStore.Delete(providerName); err != nil {
+    if err := m.credentialStore.Delete(providerName); err != nil {
         log.Debug("Failed to delete provider keyring entry", "provider", providerName, "error", err)
         errs = append(errs, errors.Join(errUtils.ErrKeyringDeletion, fmt.Errorf("provider %q: %v", providerName, err)))
-    }
+    } else {
+        succeeded++
+    }
...
-    if provider, exists := m.providers[providerName]; exists {
+    if provider, exists := m.providers[providerName]; exists {
         if err := provider.Logout(ctx); err != nil {
             log.Debug("Provider logout failed", "provider", providerName, "error", err)
             errs = append(errs, errors.Join(errUtils.ErrProviderLogout, fmt.Errorf("provider %q: %v", providerName, err)))
-        }
+        } else {
+            succeeded++
+        }
     }
...
-    if len(errs) > 0 {
-        return errors.Join(append([]error{errUtils.ErrLogoutFailed}, errs...)...)
-    }
+    if len(errs) > 0 {
+        if succeeded > 0 {
+            return errors.Join(append([]error{errUtils.ErrPartialLogout}, errs...)...)
+        }
+        return errors.Join(append([]error{errUtils.ErrLogoutFailed}, errs...)...)
+    }

841-856: Propagate partial‑success semantics in LogoutAll.

Same issue as provider path; always returning ErrLogoutFailed on any error.

Apply this diff:

-    var errs []error
+    var errs []error
+    succeeded := 0
...
-    for identityName := range m.config.Identities {
-        if err := m.Logout(ctx, identityName); err != nil {
+    for identityName := range m.config.Identities {
+        if err := m.Logout(ctx, identityName); err != nil {
             log.Debug("Failed to logout identity", "identity", identityName, "error", err)
             errs = append(errs, errors.Join(errUtils.ErrIdentityLogout, fmt.Errorf("identity %q: %v", identityName, err)))
-        }
+            if errors.Is(err, errUtils.ErrPartialLogout) {
+                succeeded++
+            }
+        } else {
+            succeeded++
+        }
     }
...
-    if len(errs) > 0 {
-        return errors.Join(append([]error{errUtils.ErrLogoutFailed}, errs...)...)
-    }
+    if len(errs) > 0 {
+        if succeeded > 0 {
+            return errors.Join(append([]error{errUtils.ErrPartialLogout}, errs...)...)
+        }
+        return errors.Join(append([]error{errUtils.ErrLogoutFailed}, errs...)...)
+    }

After changes, add tests that assert ErrPartialLogout on mixed outcomes.

cmd/auth_logout.go (5)

76-128: Instrument helpers with perf.Track and handle partial‑success for identity.

Add perf.Track and keep existing partial‑success printing. Also wrap interactive errors consistently (see another comment).

Apply this diff header for perf:

 func performIdentityLogout(ctx context.Context, authManager auth.AuthManager, identityName string, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performIdentityLogout")()

129-168: Instrument provider path and honor partial‑success semantics.

Print “logged out with warnings” and exit 0 when ErrPartialLogout is returned.

Apply this diff:

 func performProviderLogout(ctx context.Context, authManager auth.AuthManager, providerName string, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performProviderLogout")()
...
-    if err := authManager.LogoutProvider(ctx, providerName); err != nil {
-        u.PrintfMessageToTUI("✗ **Provider logout failed**\n\n")
-        u.PrintfMessageToTUI("Error: %v\n\n", err)
-        return err
-    }
+    if err := authManager.LogoutProvider(ctx, providerName); err != nil {
+        if errors.Is(err, errUtils.ErrPartialLogout) {
+            u.PrintfMessageToTUI("✓ **Provider logout completed with warnings**\n\n")
+            u.PrintfMessageToTUI("Some credentials could not be removed:\n  %v\n\n", err)
+        } else {
+            u.PrintfMessageToTUI("✗ **Provider logout failed**\n\n")
+            u.PrintfMessageToTUI("Error: %v\n\n", err)
+            return err
+        }
+    }

247-274: Instrument logout-all and honor partial‑success semantics.

Match PRD exit behavior for partial success.

Apply this diff:

 func performLogoutAll(ctx context.Context, authManager auth.AuthManager, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performLogoutAll")()
...
-    if err := authManager.LogoutAll(ctx); err != nil {
-        u.PrintfMessageToTUI("✗ **Logout all failed**\n\n")
-        u.PrintfMessageToTUI("Error: %v\n\n", err)
-        return err
-    }
+    if err := authManager.LogoutAll(ctx); err != nil {
+        if errors.Is(err, errUtils.ErrPartialLogout) {
+            u.PrintfMessageToTUI("✓ **Logout all completed with warnings**\n\n")
+            u.PrintfMessageToTUI("Some credentials could not be removed:\n  %v\n\n", err)
+        } else {
+            u.PrintfMessageToTUI("✗ **Logout all failed**\n\n")
+            u.PrintfMessageToTUI("Error: %v\n\n", err)
+            return err
+        }
+    }

170-245: Wrap interactive errors and add proper argument/flag completion.

  • form.Run() errors should be wrapped with a static sentinel.
  • ComponentsArgCompletion is unrelated; provide identity/provider completions.

Apply this diff:

-    if err := form.Run(); err != nil {
-        return err
-    }
+    if err := form.Run(); err != nil {
+        return errors.Join(errUtils.ErrUnsupportedInputType, err)
+    }

And replace the completion:

-    ValidArgsFunction:  ComponentsArgCompletion,
+    ValidArgsFunction:  authIdentityCompletion,

Add the implementations:

+// authIdentityCompletion suggests identity names.
+func authIdentityCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+    ac, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)
+    if err != nil {
+        return nil, cobra.ShellCompDirectiveNoFileComp
+    }
+    names := make([]string, 0, len(ac.Auth.Identities))
+    for n := range ac.Auth.Identities {
+        if strings.HasPrefix(n, toComplete) {
+            names = append(names, n)
+        }
+    }
+    sort.Strings(names)
+    return names, cobra.ShellCompDirectiveNoFileComp
+}

Register provider flag completion in init():

 func init() {
     authLogoutCmd.Flags().String("provider", "", "Logout from specific provider")
     authLogoutCmd.Flags().Bool("dry-run", false, "Preview what would be removed without deleting")
+    authLogoutCmd.RegisterFlagCompletionFunc("provider", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+        ac, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)
+        if err != nil {
+            return nil, cobra.ShellCompDirectiveNoFileComp
+        }
+        out := make([]string, 0, len(ac.Auth.Providers))
+        for n := range ac.Auth.Providers {
+            if strings.HasPrefix(n, toComplete) {
+                out = append(out, n)
+            }
+        }
+        sort.Strings(out)
+        return out, cobra.ShellCompDirectiveNoFileComp
+    })
     authCmd.AddCommand(authLogoutCmd)
 }

Add imports:

-    "github.com/charmbracelet/huh"
+    "github.com/charmbracelet/huh"
+    "sort"
+    "strings"

145-152: Optional: cross‑platform path hints in UI.

Hardcoding “~/.aws/atmos/…” can confuse Windows users. Consider deriving display paths with os.UserHomeDir() + filepath.Join and printing them.

Also applies to: 247-257

pkg/auth/manager_logout_test.go (1)

350-389: Add tests for partial‑success signaling in provider/all paths.

After updating manager to return ErrPartialLogout when some steps succeed, assert errors.Is(err, ErrPartialLogout) in these cases.

Also applies to: 402-427

docs/prd/auth-logout.md (2)

147-155: Add language identifiers to fenced code blocks.

Markdown lint MD040: specify a language for code fences.

Apply this diff:

-```
+```text
 ? Choose what to logout from:
   ❯ Identity: dev-admin
   ...
-```
+```
...
-```
+```text
 ⚠️  Important: This command only removes locally cached credentials.
 ...
-```
+```

Also applies to: 594-605


130-141: Optional: add “Examples” section in CLI docs and mirror CLI output styling.

Helps align UX, especially around partial-success exit behavior.

Also applies to: 184-198

pkg/auth/types/mock_interfaces.go (2)

7-14: Import groups: stdlib, third‑party, Atmos.

Project guideline wants three groups. Consider post‑gen formatting so this file stays compliant without manual edits.

Apply after-generation reordering (example):

 import (
   context "context"
   reflect "reflect"
   time "time"
 
-  schema "github.com/cloudposse/atmos/pkg/schema"
-  gomock "github.com/golang/mock/gomock"
+  gomock "github.com/golang/mock/gomock"
+
+  schema "github.com/cloudposse/atmos/pkg/schema"
 )

1-1: Reproducible generation: pin mockgen + go:generate.

To avoid drift, pin mockgen and add a go:generate in interfaces.go (not this file).

Example (in pkg/auth/types/interfaces.go):

//go:generate go run github.com/golang/mock/[email protected] -source=interfaces.go -destination=mock_interfaces.go -package=types

And pin in tools.go:

//go:build tools

package tools

import _ "github.com/golang/mock/mockgen"
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6e04105 and 506bda1.

📒 Files selected for processing (22)
  • cmd/auth_logout.go (1 hunks)
  • docs/prd/auth-logout.md (1 hunks)
  • errors/errors.go (1 hunks)
  • pkg/auth/cloud/aws/files.go (1 hunks)
  • pkg/auth/cloud/aws/files_logout_test.go (1 hunks)
  • pkg/auth/hooks_test.go (1 hunks)
  • pkg/auth/identities/aws/assume_role.go (1 hunks)
  • pkg/auth/identities/aws/permission_set.go (1 hunks)
  • pkg/auth/identities/aws/user.go (1 hunks)
  • pkg/auth/identities/aws/user_test.go (1 hunks)
  • pkg/auth/manager.go (1 hunks)
  • pkg/auth/manager_logout_test.go (1 hunks)
  • pkg/auth/manager_test.go (4 hunks)
  • pkg/auth/providers/aws/saml.go (2 hunks)
  • pkg/auth/providers/aws/saml_test.go (1 hunks)
  • pkg/auth/providers/aws/sso.go (1 hunks)
  • pkg/auth/providers/github/oidc.go (1 hunks)
  • pkg/auth/types/interfaces.go (4 hunks)
  • pkg/auth/types/mock_interfaces.go (1 hunks)
  • website/blog/2025-10-17-auth-logout-feature.md (1 hunks)
  • website/docs/cli/commands/auth/logout.mdx (1 hunks)
  • website/docs/cli/commands/auth/user-configure.mdx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/providers/github/oidc.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/manager_test.go
  • pkg/auth/identities/aws/user_test.go
  • pkg/auth/hooks_test.go
  • pkg/auth/providers/aws/sso.go
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/cloud/aws/files_logout_test.go
  • pkg/auth/manager_logout_test.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/providers/aws/saml.go
  • pkg/auth/manager.go
  • pkg/auth/types/mock_interfaces.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods; applies to single-line, multi-line, inline, and documentation comments (golangci-lint godot).
Group imports into three sections (stdlib, 3rd-party, Atmos), separated by blank lines; sort alphabetically within each group; preserve existing aliases.
Configuration loading must use Viper with precedence CLI → ENV → files → defaults; bind config name atmos and add path, AutomaticEnv, and ATMOS prefix.
All errors must be wrapped using static errors (defined in errors/errors.go); use errors.Join for multiple errors; fmt.Errorf with %w for context; use errors.Is for checks; never compare error strings.
Distinguish structured logging from UI output: UI prompts/status/errors to stderr; data/results to stdout; never use logging for UI.
Most text UI must go to stderr; only data/results to stdout; prefer utils.PrintfMessageToTUI for UI messages.
All new configurations must support Go templating using existing utilities and available template functions.
Prefer SDKs over external binaries for cross-platform support; use filepath/os/runtime for portability.
For non-standard execution paths, capture telemetry via telemetry.CaptureCmd or telemetry.CaptureCmdString without user data.
80% minimum coverage on new/changed lines and include unit tests for new features; add integration tests for CLI using tests/ fixtures.
Always bind environment variables with viper.BindEnv and provide ATMOS_ alternatives for every env var.
Use structured logging with levels (Fatal>Error>Warn>Debug>Trace); avoid string interpolation and ensure logging does not affect execution.
Prefer re...

Files:

  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/providers/github/oidc.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/cloud/aws/files.go
  • errors/errors.go
  • pkg/auth/manager_test.go
  • pkg/auth/identities/aws/user_test.go
  • pkg/auth/hooks_test.go
  • pkg/auth/providers/aws/sso.go
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/cloud/aws/files_logout_test.go
  • pkg/auth/manager_logout_test.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/providers/aws/saml.go
  • cmd/auth_logout.go
  • pkg/auth/manager.go
  • pkg/auth/types/mock_interfaces.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Add defer perf.Track() to all public functions and critical private functions; include a blank line after the call; use package-prefixed names; pass atmosConfig when present, else nil.

Files:

  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/providers/github/oidc.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/cloud/aws/files.go
  • errors/errors.go
  • pkg/auth/providers/aws/sso.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/providers/aws/saml.go
  • cmd/auth_logout.go
  • pkg/auth/manager.go
  • pkg/auth/types/mock_interfaces.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases

Before committing documentation/site changes, run npm run build in website/ and fix errors, broken links, and missing images.

Files:

  • website/docs/cli/commands/auth/user-configure.mdx
  • website/docs/cli/commands/auth/logout.mdx
  • website/blog/2025-10-17-auth-logout-feature.md
website/docs/cli/commands/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Document all new commands/flags/parameters in Docusaurus under website/docs/cli/commands/, using definition lists for args/flags and the prescribed frontmatter and sections.

Files:

  • website/docs/cli/commands/auth/user-configure.mdx
  • website/docs/cli/commands/auth/logout.mdx
website/docs/**

📄 CodeRabbit inference engine (CLAUDE.md)

website/docs/**: After modifying any docs under website/docs/, build the website (npm run build) and ensure no errors.
Document user-facing template functions in the website if applicable.

Files:

  • website/docs/cli/commands/auth/user-configure.mdx
  • website/docs/cli/commands/auth/logout.mdx
errors/errors.go

📄 CodeRabbit inference engine (CLAUDE.md)

Define all static errors centrally in errors/errors.go as package-level vars.

Files:

  • errors/errors.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven unit tests for pure functions and focus on behavior; co-locate tests; target >80% coverage for pkg/ and internal/exec/.
Always use t.Skipf() with a clear reason; never use t.Skip() or t.Skipf without a reason.

Files:

  • pkg/auth/manager_test.go
  • pkg/auth/identities/aws/user_test.go
  • pkg/auth/hooks_test.go
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/cloud/aws/files_logout_test.go
  • pkg/auth/manager_logout_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for packages live under pkg/ alongside implementation files.

Files:

  • pkg/auth/manager_test.go
  • pkg/auth/identities/aws/user_test.go
  • pkg/auth/hooks_test.go
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/cloud/aws/files_logout_test.go
  • pkg/auth/manager_logout_test.go
website/blog/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

website/blog/*.md: For PRs labeled minor or major, include a blog post in website/blog/YYYY-MM-DD-*.md following the template and include after the introduction.
Tag blog posts appropriately: user-facing (feature/enhancement/bugfix) or contributor (contributors) plus relevant technical tags.

Files:

  • website/blog/2025-10-17-auth-logout-feature.md
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate

cmd/**/*.go: Use utils.PrintfMarkdown() to render embedded markdown content for CLI command help/examples.
One Cobra command per file in cmd/; keep files focused and small.

Files:

  • cmd/auth_logout.go
**/{mock_*.go,mock/*.go}

📄 CodeRabbit inference engine (CLAUDE.md)

Generate and keep mocks alongside the interfaces they mock; mocks are excluded from coverage.

Files:

  • pkg/auth/types/mock_interfaces.go
🧠 Learnings (1)
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/{mock_*.go,mock/*.go} : Generate and keep mocks alongside the interfaces they mock; mocks are excluded from coverage.

Applied to files:

  • pkg/auth/types/mock_interfaces.go
🧬 Code graph analysis (12)
pkg/auth/identities/aws/permission_set.go (1)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/providers/github/oidc.go (1)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/identities/aws/user.go (3)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (43-51)
errors/errors.go (1)
  • ErrLogoutFailed (374-374)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/cloud/aws/files.go (1)
errors/error_funcs.go (1)
  • CheckErrorAndPrint (29-52)
pkg/auth/providers/aws/sso.go (3)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (43-51)
errors/errors.go (1)
  • ErrLogoutFailed (374-374)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/cloud/aws/files_logout_test.go (1)
pkg/auth/cloud/aws/files.go (1)
  • AWSFileManager (38-40)
pkg/auth/manager_logout_test.go (4)
pkg/auth/types/mock_interfaces.go (6)
  • MockCredentialStore (501-504)
  • MockProvider (17-20)
  • MockIdentity (140-143)
  • NewMockCredentialStore (512-516)
  • NewMockProvider (28-32)
  • NewMockIdentity (151-155)
pkg/schema/schema_auth.go (2)
  • AuthConfig (4-8)
  • IdentityVia (42-45)
pkg/auth/types/interfaces.go (2)
  • Provider (13-37)
  • Identity (40-64)
errors/errors.go (4)
  • ErrIdentityNotInConfig (380-380)
  • ErrPartialLogout (375-375)
  • ErrLogoutFailed (374-374)
  • ErrProviderNotInConfig (381-381)
pkg/auth/identities/aws/assume_role.go (1)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/providers/aws/saml.go (3)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (43-51)
errors/errors.go (1)
  • ErrLogoutFailed (374-374)
pkg/logger/log.go (1)
  • Debug (24-26)
cmd/auth_logout.go (6)
cmd/cmd_utils.go (1)
  • ComponentsArgCompletion (768-790)
pkg/config/config.go (1)
  • InitCliConfig (25-62)
errors/errors.go (6)
  • ErrFailedToInitializeAtmosConfig (117-117)
  • ErrAuthManager (334-334)
  • ErrIdentityNotInConfig (380-380)
  • ErrPartialLogout (375-375)
  • ErrProviderNotInConfig (381-381)
  • ErrInvalidLogoutOption (382-382)
pkg/auth/types/interfaces.go (1)
  • AuthManager (67-117)
pkg/utils/log_utils.go (1)
  • PrintfMessageToTUI (33-35)
internal/tui/utils/utils.go (1)
  • NewAtmosHuhTheme (85-93)
pkg/auth/manager.go (4)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/logger/log.go (3)
  • Errorf (59-61)
  • Debug (24-26)
  • Info (34-36)
errors/errors.go (7)
  • ErrIdentityNotInConfig (380-380)
  • ErrKeyringDeletion (377-377)
  • ErrProviderLogout (378-378)
  • ErrIdentityLogout (379-379)
  • ErrPartialLogout (375-375)
  • ErrLogoutFailed (374-374)
  • ErrProviderNotInConfig (381-381)
pkg/auth/types/interfaces.go (1)
  • Provider (13-37)
pkg/auth/types/mock_interfaces.go (3)
pkg/schema/schema.go (3)
  • Context (381-396)
  • Validate (188-190)
  • ConfigAndStacksInfo (460-539)
pkg/auth/types/interfaces.go (4)
  • ICredentials (152-158)
  • AuthManager (67-117)
  • Identity (40-64)
  • Provider (13-37)
pkg/auth/types/whoami.go (1)
  • WhoamiInfo (6-22)
🪛 LanguageTool
website/docs/cli/commands/auth/logout.mdx

[style] ~18-~18: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ing Local Credentials Only This command only removes **credentials stored on your lo...

(ADVERB_REPETITION_PREMIUM)


[grammar] ~89-~89: Ensure spelling is correct
Context: ...s an interactive menu to choose what to logout from: ``` ? Choose what to logout from...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~217-~217: Ensure spelling is correct
Context: ...o completely end your session and fully logout: 1. Run atmos auth logout to remove local ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~346-~346: Ensure spelling is correct
Context: ...ation chain. ## Best Practices ### 1. Logout When Switching Contexts When switching...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~348-~348: Ensure spelling is correct
Context: ...n different identities or environments, logout first to ensure clean state: ```shell ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

website/blog/2025-10-17-auth-logout-feature.md

[grammar] ~178-~178: Please add a punctuation mark at the end of paragraph.
Context: ...he browser session 4. Close all browser windows The command displays this warning afte...

(PUNCTUATION_PARAGRAPH_END)


[grammar] ~307-~307: Please add a punctuation mark at the end of paragraph.
Context: ...ath` package for platform-specific path separators ### Error Handling Following Atmos er...

(PUNCTUATION_PARAGRAPH_END)


[grammar] ~316-~316: Please add a punctuation mark at the end of paragraph.
Context: ...on-fatal errors - Reports all errors at completion ### Interface Extensions The logout f...

(PUNCTUATION_PARAGRAPH_END)

docs/prd/auth-logout.md

[typographical] ~57-~57: Consider using typographic quotation marks here.
Context: ...elet Huh for styled selection - Allow "All identities" option - Apply Atmos theme to prompts...

(EN_QUOTES)


[grammar] ~626-~626: Ensure spelling is correct
Context: ...lement styled output with Charmbracelet lipgloss - [ ] Add progress indicators for multi-st...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[typographical] ~693-~693: Consider using typographic quotation marks here.
Context: ...upport --all flag or just interactive "All identities" option? Decision: Use interactive ...

(EN_QUOTES)

🪛 markdownlint-cli2 (0.18.1)
website/blog/2025-10-17-auth-logout-feature.md

40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


67-67: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


88-88: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


109-109: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


128-128: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


149-149: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


209-209: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/prd/auth-logout.md

147-147: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


594-594: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Summary
🔇 Additional comments (24)
pkg/auth/providers/aws/sso.go (1)

237-251: LGTM! Clean logout implementation.

The method follows the established pattern: creates the file manager, performs cleanup, logs the outcome, and properly wraps errors with the sentinel.

pkg/auth/identities/aws/user_test.go (1)

79-79: LGTM! Test stub satisfies interface.

The no-op Logout implementation on stubUser is appropriate for test isolation.

website/docs/cli/commands/auth/user-configure.mdx (1)

11-15: LGTM! Consistent doc component usage.

Wrapping the introductory text in the Intro component aligns with the documentation pattern used elsewhere in the PR.

pkg/auth/identities/aws/user.go (1)

356-372: LGTM! Identity logout implementation matches pattern.

The method correctly uses "aws-user" as the provider name (matching the constant), performs cleanup, and wraps errors properly.

pkg/auth/providers/aws/saml_test.go (1)

111-113: LGTM! Test stub extended for new interface.

The no-op logout methods on stubSamlMgr satisfy the expanded AuthManager interface for test purposes.

pkg/auth/manager_test.go (4)

286-286: LGTM! Test stub updated for Provider interface.

The no-op Logout on testProvider satisfies the updated interface contract.


478-478: LGTM! Test stub updated for Identity interface.


550-550: LGTM! Test stub updated.


794-794: LGTM! Test stub completed.

pkg/auth/types/interfaces.go (4)

3-3: LGTM! Mock generation enabled.

The go:generate directive will automate mock creation for testing.


33-36: LGTM! Provider logout interface added.

The method signature and best-effort semantics are clearly documented.


61-63: LGTM! Identity logout interface added.


106-116: LGTM! AuthManager logout methods added.

The three logout variants (identity-specific, provider-specific, and all) provide comprehensive coverage with clear documentation of best-effort cleanup semantics.

pkg/auth/providers/github/oidc.go (1)

204-210: LGTM! Appropriate no-op logout.

GitHub OIDC provider has no local files to clean up—credentials live in the keyring and are handled by the manager. The debug log and comment make this clear.

pkg/auth/hooks_test.go (1)

50-60: LGTM!

The stub implementations correctly satisfy the updated AuthManager interface for testing purposes. The nil returns are appropriate for test stubs.

pkg/auth/cloud/aws/files_logout_test.go (3)

9-90: LGTM!

Well-structured table-driven tests covering the important scenarios: existing directories, non-existent directories, and nested structures. The use of t.TempDir() ensures proper cleanup.


92-191: LGTM!

Comprehensive tests for CleanupAll covering multiple providers, empty directories, and complex nested structures. Good coverage of edge cases.


193-265: LGTM!

Excellent idempotency tests for both Cleanup and CleanupAll. These ensure the methods can be safely called multiple times without errors.

website/docs/cli/commands/auth/logout.mdx (1)

1-392: LGTM!

Comprehensive documentation covering usage, examples, security considerations, troubleshooting, and best practices. The warnings about browser sessions are appropriately prominent. The structure and content align well with the feature implementation.

Note: The LanguageTool warnings about "logout" spelling are false positives, as "logout" is the actual command name.

cmd/auth_logout.go (1)

43-52: Fix multiple %w wrapping when returning initialization errors.

Use errors.Join or a single %w to avoid fmt.Errorf panics.

Apply this diff:

-    if err != nil {
-        return fmt.Errorf("%w: %w", errUtils.ErrFailedToInitializeAtmosConfig, err)
-    }
+    if err != nil {
+        return errors.Join(errUtils.ErrFailedToInitializeAtmosConfig, err)
+    }
...
-    if err != nil {
-        return fmt.Errorf("%w: %w", errUtils.ErrAuthManager, err)
-    }
+    if err != nil {
+        return errors.Join(errUtils.ErrAuthManager, err)
+    }
⛔ Skipped due to learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/*.go : All errors must be wrapped using static errors (defined in errors/errors.go); use errors.Join for multiple errors; fmt.Errorf with %w for context; use errors.Is for checks; never compare error strings.
Learnt from: osterman
PR: cloudposse/atmos#740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.
pkg/auth/manager_logout_test.go (1)

226-264: Review comment is inaccurate; test expectations correctly reflect actual behavior.

The test expectation of provider.Logout being called 3 times is correct. Here's why:

  1. LogoutProvider iterates through 2 identities and calls m.Logout for each (line 804)
  2. Each Logout call independently invokes provider.Logout once (line 737)
  3. Then LogoutProvider calls provider.Logout again directly (line 818)

This results in: 2 (from identity loop) + 1 (direct) = 3 calls. This is intentional, not redundant—the provider cleanup happens both during identity logout and explicitly at the provider level.

Consolidating to 1x would alter the logout semantics and require architectural changes. The current test accurately validates the implemented behavior.

Likely an incorrect or invalid review comment.

pkg/auth/manager.go (1)

724-731: I need to verify the Go version requirement since the go.mod check produced no output:Perfect. Before Go 1.20, fmt.Errorf() is able to support only one occurrence of %w format verb. However, with Go 1.20, fmt.Errorf now accepts multiple %w format specifiers and by having multiple %w, the function fmt.Errorf() will instead create a list of errors, returning error[] instead of error.

Now comparing with the learnings: the learning explicitly validates that the pattern in use (fmt.Errorf(errUtils.ErrWrappingFormat, ...) with ErrWrappingFormat = "%w: %w") is correct. The review is based on outdated Go 1.13-1.19 behavior where multiple %w would fail. But this codebase is using the pattern extensively, which indicates it targets Go 1.20+.

This review comment is incorrect—no code changes are needed.

The multiple %w pattern is valid in Go 1.20+ and has been validated as correct by a previous reviewer. The code does not panic and uses the proper error wrapping approach for the target Go version.

Likely an incorrect or invalid review comment.

pkg/auth/types/mock_interfaces.go (2)

16-737: LGTM: mocks match updated interfaces (incl. Logout) and are ready for tests.

Signatures align with Provider, Identity, AuthManager, CredentialStore, Validator, and ICredentials. Good placement alongside the interfaces.


1-4: Generated mocks correctly follow the standard exclusion pattern.

The file has the proper Code generated by MockGen. DO NOT EDIT. header, and .golangci.yml is configured with generated: lax for both linters and formatters. This setup correctly exempts generated mocks from lint checks like godot and missing documentation requirements.

@osterman osterman added the minor New features that do not break anything label Oct 17, 2025
Add support for configuring the AWS credentials base directory path
through provider spec configuration with proper precedence handling.

- Add files.base_path configuration option to provider spec
- Update AWSFileManager to accept optional base_path parameter
- Implement precedence: spec config > env var > default ~/.aws/atmos
- Add GetFilesBasePath helper to extract path from provider spec
- Update all providers (SSO, SAML) to use configured base_path
- Add GetFilesDisplayPath method to AuthManager interface
- Support tilde expansion for user home directory paths
- Use viper.GetString for environment variable access
- Update golden snapshot for auth invalid-command test

This allows users to customize where AWS credential files are stored
on a per-provider basis, enabling XDG-compliant paths or custom
locations while maintaining backward compatibility with the default
~/.aws/atmos directory.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Updated the `atmos auth logout` command to show the actual configured
AWS files path instead of hardcoded `~/.aws/atmos/` in dry-run mode.

Changes:
- performIdentityLogout: Use authManager.GetFilesDisplayPath() for provider path
- performProviderLogout: Use authManager.GetFilesDisplayPath() for provider path
- performLogoutAll: Enhanced to show all provider paths using GetFilesDisplayPath()

This ensures users see the correct path whether using the default ~/.aws/atmos
or a custom path configured via spec.files.base_path.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
osterman and others added 2 commits October 17, 2025 15:57
Added validation to ensure spec.files.base_path is properly formatted
when configured in AWS auth providers (SSO and SAML).

Changes:
- Created ValidateFilesBasePath() function in pkg/auth/cloud/aws/spec.go
- Updated SSO and SAML provider Validate() methods to call validation
- Added comprehensive tests covering valid and invalid path scenarios
- Validation checks for: empty/whitespace paths, invalid characters

This ensures configuration errors are caught early during auth validation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Updated documentation to explain the configurable AWS files base path
feature for auth logout command.

Changes:
- PRD: Added Configuration section with spec.files.base_path examples
- PRD: Updated FR-004 to mention configurable base path
- CLI docs: Added "Advanced Configuration" section with full examples
- CLI docs: Documented configuration precedence and validation
- CLI docs: Added example with environment variable override

The documentation explains:
- How to configure custom file paths in atmos.yaml
- Configuration precedence (config > env var > default)
- Path validation rules
- Use cases for custom paths (containers, multi-user, etc.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
pkg/auth/identities/aws/permission_set.go (1)

145-151: Path mismatch: Environment ignores provider files.base_path.

Creating NewAWSFileManager("") ignores a provider’s configured files.base_path. Downstream cleanup (provider Logout) uses the configured base path, so env points to one path while files may be written/cleaned in another.

Pass the provider’s configured base path into the file manager. Options:

  • Thread base path from config/manager into Environment.
  • Or expose a helper to resolve base path by provider name and use it here.

This prevents stale creds and inconsistent AWS_* env paths.

pkg/auth/providers/aws/saml.go (1)

121-125: Fix error wrapping to preserve sentinels and causes.

Several fmt.Errorf calls use %v for the inner error, breaking errors.Is checks per guidelines. Wrap underlying errors with %w or join with the sentinel + contextual error.

- return nil, fmt.Errorf("%w: failed to create SAML client: %v", errUtils.ErrInvalidProviderConfig, err)
+ return nil, errors.Join(errUtils.ErrInvalidProviderConfig, fmt.Errorf("failed to create SAML client: %w", err))

- return nil, fmt.Errorf("%w: failed to decode assertion: %v", errUtils.ErrAwsSAMLDecodeFailed, err)
+ return nil, errors.Join(errUtils.ErrAwsSAMLDecodeFailed, fmt.Errorf("failed to decode assertion: %w", err))

- return nil, fmt.Errorf("%w: extract AWS roles: %v", errUtils.ErrAwsSAMLDecodeFailed, err)
+ return nil, errors.Join(errUtils.ErrAwsSAMLDecodeFailed, fmt.Errorf("extract AWS roles: %w", err))

- return nil, fmt.Errorf("%w: parse AWS roles: %v", errUtils.ErrAwsSAMLDecodeFailed, err)
+ return nil, errors.Join(errUtils.ErrAwsSAMLDecodeFailed, fmt.Errorf("parse AWS roles: %w", err))

- return nil, fmt.Errorf("%w: failed to assume role with SAML: %v", errUtils.ErrAuthenticationFailed, err)
+ return nil, errors.Join(errUtils.ErrAuthenticationFailed, fmt.Errorf("failed to assume role with SAML: %w", err))

- return nil, fmt.Errorf("%w: failed to create AWS config: %v", errUtils.ErrAuthenticationFailed, err)
+ return nil, errors.Join(errUtils.ErrAuthenticationFailed, fmt.Errorf("failed to create AWS config: %w", err))

- return nil, fmt.Errorf("%w: failed to assume role with SAML: %v", errUtils.ErrAuthenticationFailed, err)
+ return nil, errors.Join(errUtils.ErrAuthenticationFailed, fmt.Errorf("failed to assume role with SAML: %w", err))

Also applies to: 132-136, 137-143, 150-154, 253-256, 268-271

pkg/auth/identities/aws/user.go (1)

150-156: Fix error wrapping to follow guidelines.

Use %w and/or errors.Join instead of %v to keep sentinel checks working.

- if err := awsFileManager.WriteCredentials(awsUserProviderName, i.name, creds); err != nil {
-   return fmt.Errorf("%w: failed to write AWS credentials: %v", errUtils.ErrAwsAuth, err)
+ if err := awsFileManager.WriteCredentials(awsUserProviderName, i.name, creds); err != nil {
+   return errors.Join(errUtils.ErrAwsAuth, fmt.Errorf("failed to write AWS credentials: %w", err))
 }
- if err := awsFileManager.WriteConfig(awsUserProviderName, i.name, region, ""); err != nil {
-   return fmt.Errorf("%w: failed to write AWS config: %v", errUtils.ErrAwsAuth, err)
+ if err := awsFileManager.WriteConfig(awsUserProviderName, i.name, region, ""); err != nil {
+   return errors.Join(errUtils.ErrAwsAuth, fmt.Errorf("failed to write AWS config: %w", err))
 }

- if err != nil {
-   return nil, fmt.Errorf("%w: failed to load AWS config: %v", errUtils.ErrAwsAuth, err)
+ if err != nil {
+   return nil, errors.Join(errUtils.ErrAwsAuth, fmt.Errorf("failed to load AWS config: %w", err))
 }

- if err := i.writeAWSFiles(sessionCreds, region); err != nil {
-   return nil, fmt.Errorf("%w: failed to write AWS files: %v", errUtils.ErrAwsAuth, err)
+ if err := i.writeAWSFiles(sessionCreds, region); err != nil {
+   return nil, errors.Join(errUtils.ErrAwsAuth, fmt.Errorf("failed to write AWS files: %w", err))
 }

- if err := form.Run(); err != nil {
-   return "", fmt.Errorf("%w: failed to get MFA token: %v", errUtils.ErrAuthenticationFailed, err)
+ if err := form.Run(); err != nil {
+   return "", errors.Join(errUtils.ErrAuthenticationFailed, fmt.Errorf("failed to get MFA token: %w", err))
 }

- if err != nil {
-   return nil, fmt.Errorf("%w: AWS user identity %q authentication failed: %v", errUtils.ErrAuthenticationFailed, identityName, err)
+ if err != nil {
+   return nil, errors.Join(errUtils.ErrAuthenticationFailed, fmt.Errorf("AWS user identity %q authentication failed: %w", identityName, err))
 }

Also applies to: 179-182, 221-223, 236-238, 336-338

♻️ Duplicate comments (1)
cmd/auth_logout.go (1)

39-54: Add perf tracking at command entrypoint.

Per guidelines, add defer perf.Track after config init to profile this command.

 import (
   "context"
   "errors"
   "fmt"
+  "github.com/cloudposse/atmos/pkg/perf"
...
 func executeAuthLogoutCommand(cmd *cobra.Command, args []string) error {
   handleHelpRequest(cmd, args)

   // Load atmos config.
   atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false)
   if err != nil {
     return fmt.Errorf("%w: %w", errUtils.ErrFailedToInitializeAtmosConfig, err)
   }
+
+  defer perf.Track(&atmosConfig, "cmd.AuthLogout.execute")()
+
   // Create auth manager.
🧹 Nitpick comments (13)
pkg/auth/cloud/aws/spec.go (1)

14-24: Unit tests for spec parsing.

Please add a tiny table‑driven test covering nil provider/spec, wrong types, and valid base_path. I can draft it.

pkg/auth/cloud/aws/setup.go (1)

13-18: Add perf.Track to exported functions.

Per guidelines, add defer perf.Track() at the top of SetupFiles and SetEnvironmentVariables (package‑prefixed name, blank line after).

Also applies to: 44-57

pkg/auth/identities/aws/assume_role.go (1)

97-103: Clamp AssumeRole duration to STS limits.

DurationSeconds should be clamped to [900, 43200] to avoid API errors (you already clamp in SAML). Add min/max guards here too.

- if duration, err := time.ParseDuration(durationStr); err == nil {
-   input.DurationSeconds = aws.Int32(int32(duration.Seconds()))
+ if duration, err := time.ParseDuration(durationStr); err == nil {
+   secs := int32(duration.Seconds())
+   if secs < 900 {
+     secs = 900
+   } else if secs > 43200 {
+     secs = 43200
+   }
+   input.DurationSeconds = aws.Int32(secs)
pkg/auth/identities/aws/user.go (1)

259-278: Enable accessible mode for MFA prompt.

Support screen readers/non-TTY by enabling huh accessible mode behind an env flag.

+import "os"
...
 func newMfaForm(longLivedCreds *types.AWSCredentials, mfaToken *string) *huh.Form {
-  form := huh.NewForm(
+  form := huh.NewForm(
       ...
   )
-  return form
+  return form.WithAccessible(os.Getenv("ACCESSIBLE") != "")
 }

Based on learnings.

cmd/auth_logout.go (3)

20-37: Use identity/provider completions instead of component completion.

ValidArgsFunction points to ComponentsArgCompletion. Provide a lightweight completer for identities (and flags for providers) to improve UX.


296-300: Bind flags with Viper (ENV parity).

Bind --provider/--dry-run to Viper (and ATMOS_ equivalents) for consistent CLI/ENV handling per guidelines.


39-74: Capture telemetry for non-standard path.

Add telemetry.CaptureCmd/CaptureCmdString (no user data) at the start/end of execution to observe usage of logout flows.

pkg/auth/manager.go (2)

862-885: Optional: de-duplicate provider cleanup in LogoutAll.

Calling Logout for each identity may trigger provider.Logout many times. Consider tracking visited providers and calling provider.Logout once per provider to reduce redundant I/O.


334-360: Minor: avoid hardcoded Unix-y fallback in display path and rely on file manager when possible.

If NewAWSFileManager fails, we return "~/.aws/atmos". On Windows this looks odd. Consider returning an empty string or a best-effort computed path via homedir.Dir + filepath.Join, or surface an error to the caller to decide.

pkg/auth/cloud/aws/files.go (4)

48-75: Prefer internal homedir utilities over external dependency.

The repo has pkg/config/homedir with Expand/Dir. Using it avoids duplicate logic and keeps behavior consistent across Atmos.

Apply this diff:

@@
-import (
+import (
   "errors"
   "fmt"
   "os"
   "path/filepath"
   "strings"
 
-  homedir "github.com/mitchellh/go-homedir"
+  homedir "github.com/cloudposse/atmos/pkg/config/homedir"
   "github.com/spf13/viper"
   ini "gopkg.in/ini.v1"
@@
-    expanded, err := homedir.Expand(basePath)
+    expanded, err := homedir.Expand(basePath)
@@
-  } else if envPath := viper.GetString("ATMOS_AWS_FILES_BASE_PATH"); envPath != "" {
+  } else if envPath := viper.GetString("ATMOS_AWS_FILES_BASE_PATH"); envPath != "" {
@@
-    homeDir, err := homedir.Dir()
+    homeDir, err := homedir.Dir()

201-208: Windows-friendly display path.

strings.HasPrefix on raw paths can fail across separators/case. Normalize before compare.

Apply this diff:

 func (m *AWSFileManager) GetDisplayPath() string {
-  homeDir, err := homedir.Dir()
-  if err == nil && homeDir != "" && strings.HasPrefix(m.baseDir, homeDir) {
-    return strings.Replace(m.baseDir, homeDir, "~", 1)
+  homeDir, err := homedir.Dir()
+  if err == nil && homeDir != "" {
+    base := filepath.Clean(m.baseDir)
+    hd := filepath.Clean(homeDir)
+    if strings.HasPrefix(strings.ToLower(base), strings.ToLower(hd+string(os.PathSeparator))) || strings.EqualFold(base, hd) {
+      return strings.Replace(base, hd, "~", 1)
+    }
   }
-  return m.baseDir
+  return filepath.Clean(m.baseDir)
 }

235-245: Simplify RemoveAll error handling.

os.RemoveAll already returns nil when the path doesn’t exist; the NotExist branch is redundant.

Apply this diff:

 func (m *AWSFileManager) Cleanup(providerName string) error {
   providerDir := filepath.Join(m.baseDir, providerName)
 
-  if err := os.RemoveAll(providerDir); err != nil {
-    // If directory doesn't exist, that's not an error (already cleaned up).
-    if os.IsNotExist(err) {
-      return nil
-    }
+  if err := os.RemoveAll(providerDir); err != nil {
     errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, providerDir, "failed to cleanup AWS files")
     return ErrCleanupAWSFiles
   }
   return nil
 }

247-259: Same here: RemoveAll already no-ops on missing paths.

Drop the NotExist handling to reduce branches.

Apply this diff:

 func (m *AWSFileManager) CleanupAll() error {
-  if err := os.RemoveAll(m.baseDir); err != nil {
-    // If directory doesn't exist, that's not an error (already cleaned up).
-    if os.IsNotExist(err) {
-      return nil
-    }
+  if err := os.RemoveAll(m.baseDir); err != nil {
     errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, m.baseDir, "failed to cleanup all AWS files")
     return ErrCleanupAWSFiles
   }
   return nil
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 506bda1 and c1ca11e.

📒 Files selected for processing (15)
  • cmd/auth_logout.go (1 hunks)
  • pkg/auth/cloud/aws/files.go (4 hunks)
  • pkg/auth/cloud/aws/setup.go (2 hunks)
  • pkg/auth/cloud/aws/spec.go (1 hunks)
  • pkg/auth/hooks_test.go (2 hunks)
  • pkg/auth/identities/aws/assume_role.go (2 hunks)
  • pkg/auth/identities/aws/permission_set.go (2 hunks)
  • pkg/auth/identities/aws/user.go (3 hunks)
  • pkg/auth/manager.go (3 hunks)
  • pkg/auth/providers/aws/saml.go (2 hunks)
  • pkg/auth/providers/aws/saml_test.go (1 hunks)
  • pkg/auth/providers/aws/sso.go (1 hunks)
  • pkg/auth/types/interfaces.go (5 hunks)
  • pkg/auth/types/mock_interfaces.go (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.golden (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/snapshots/TestCLICommands_atmos_auth_invalid-command.stderr.golden
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/providers/aws/sso.go
🧰 Additional context used
📓 Path-based instructions (7)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/auth/cloud/aws/spec.go
  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/providers/aws/saml.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/types/mock_interfaces.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/cloud/aws/setup.go
  • pkg/auth/manager.go
  • pkg/auth/hooks_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods; applies to single-line, multi-line, inline, and documentation comments (golangci-lint godot).
Group imports into three sections (stdlib, 3rd-party, Atmos), separated by blank lines; sort alphabetically within each group; preserve existing aliases.
Configuration loading must use Viper with precedence CLI → ENV → files → defaults; bind config name atmos and add path, AutomaticEnv, and ATMOS prefix.
All errors must be wrapped using static errors (defined in errors/errors.go); use errors.Join for multiple errors; fmt.Errorf with %w for context; use errors.Is for checks; never compare error strings.
Distinguish structured logging from UI output: UI prompts/status/errors to stderr; data/results to stdout; never use logging for UI.
Most text UI must go to stderr; only data/results to stdout; prefer utils.PrintfMessageToTUI for UI messages.
All new configurations must support Go templating using existing utilities and available template functions.
Prefer SDKs over external binaries for cross-platform support; use filepath/os/runtime for portability.
For non-standard execution paths, capture telemetry via telemetry.CaptureCmd or telemetry.CaptureCmdString without user data.
80% minimum coverage on new/changed lines and include unit tests for new features; add integration tests for CLI using tests/ fixtures.
Always bind environment variables with viper.BindEnv and provide ATMOS_ alternatives for every env var.
Use structured logging with levels (Fatal>Error>Warn>Debug>Trace); avoid string interpolation and ensure logging does not affect execution.
Prefer re...

Files:

  • pkg/auth/cloud/aws/spec.go
  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/providers/aws/saml.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/types/mock_interfaces.go
  • cmd/auth_logout.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/cloud/aws/setup.go
  • pkg/auth/manager.go
  • pkg/auth/hooks_test.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Add defer perf.Track() to all public functions and critical private functions; include a blank line after the call; use package-prefixed names; pass atmosConfig when present, else nil.

Files:

  • pkg/auth/cloud/aws/spec.go
  • pkg/auth/identities/aws/permission_set.go
  • pkg/auth/identities/aws/user.go
  • pkg/auth/providers/aws/saml.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/identities/aws/assume_role.go
  • pkg/auth/types/mock_interfaces.go
  • cmd/auth_logout.go
  • pkg/auth/types/interfaces.go
  • pkg/auth/cloud/aws/setup.go
  • pkg/auth/manager.go
**/{mock_*.go,mock/*.go}

📄 CodeRabbit inference engine (CLAUDE.md)

Generate and keep mocks alongside the interfaces they mock; mocks are excluded from coverage.

Files:

  • pkg/auth/types/mock_interfaces.go
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate

cmd/**/*.go: Use utils.PrintfMarkdown() to render embedded markdown content for CLI command help/examples.
One Cobra command per file in cmd/; keep files focused and small.

Files:

  • cmd/auth_logout.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven unit tests for pure functions and focus on behavior; co-locate tests; target >80% coverage for pkg/ and internal/exec/.
Always use t.Skipf() with a clear reason; never use t.Skip() or t.Skipf without a reason.

Files:

  • pkg/auth/hooks_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for packages live under pkg/ alongside implementation files.

Files:

  • pkg/auth/hooks_test.go
🧠 Learnings (3)
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to cmd/**/*.go : Use Viper for managing configuration, environment variables, and flags in the CLI

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/!(*_test).go : Add `defer perf.Track()` to all public functions and critical private functions; include a blank line after the call; use package-prefixed names; pass atmosConfig when present, else nil.

Applied to files:

  • cmd/auth_logout.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
PR: cloudposse/atmos#1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/auth/manager.go
🧬 Code graph analysis (9)
pkg/auth/identities/aws/permission_set.go (2)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/identities/aws/user.go (3)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
errors/errors.go (1)
  • ErrLogoutFailed (374-374)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/providers/aws/saml.go (4)
pkg/auth/cloud/aws/spec.go (1)
  • GetFilesBasePath (9-25)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
errors/errors.go (1)
  • ErrLogoutFailed (374-374)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/cloud/aws/files.go (2)
pkg/config/homedir/homedir.go (2)
  • Expand (68-87)
  • Dir (36-63)
errors/error_funcs.go (1)
  • CheckErrorAndPrint (29-52)
pkg/auth/identities/aws/assume_role.go (2)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/types/mock_interfaces.go (3)
pkg/schema/schema.go (3)
  • Context (381-396)
  • Validate (188-190)
  • ConfigAndStacksInfo (460-539)
pkg/auth/types/interfaces.go (4)
  • ICredentials (156-162)
  • AuthManager (67-121)
  • Identity (40-64)
  • Provider (13-37)
pkg/auth/types/whoami.go (1)
  • WhoamiInfo (6-22)
cmd/auth_logout.go (7)
cmd/cmd_utils.go (1)
  • ComponentsArgCompletion (768-790)
pkg/config/config.go (1)
  • InitCliConfig (25-62)
pkg/schema/schema.go (2)
  • ConfigAndStacksInfo (460-539)
  • Context (381-396)
errors/errors.go (6)
  • ErrFailedToInitializeAtmosConfig (117-117)
  • ErrAuthManager (334-334)
  • ErrIdentityNotInConfig (380-380)
  • ErrPartialLogout (375-375)
  • ErrProviderNotInConfig (381-381)
  • ErrInvalidLogoutOption (382-382)
pkg/auth/types/interfaces.go (1)
  • AuthManager (67-121)
pkg/utils/log_utils.go (1)
  • PrintfMessageToTUI (33-35)
internal/tui/utils/utils.go (1)
  • NewAtmosHuhTheme (85-93)
pkg/auth/cloud/aws/setup.go (1)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
pkg/auth/manager.go (5)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (47-76)
pkg/auth/cloud/aws/spec.go (1)
  • GetFilesBasePath (9-25)
errors/errors.go (7)
  • ErrIdentityNotInConfig (380-380)
  • ErrKeyringDeletion (377-377)
  • ErrProviderLogout (378-378)
  • ErrIdentityLogout (379-379)
  • ErrPartialLogout (375-375)
  • ErrLogoutFailed (374-374)
  • ErrProviderNotInConfig (381-381)
pkg/auth/types/interfaces.go (1)
  • Provider (13-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Summary
🔇 Additional comments (9)
pkg/auth/identities/aws/permission_set.go (1)

266-274: No‑op Logout is fine.

Clear and documented; provider/AuthManager handle cleanup.

pkg/auth/types/interfaces.go (1)

33-37: All interface implementations verified—no issues found.

Logout is implemented across all concrete providers (sso, oidc, saml) and identities (user, permissionSet, assumeRole). Mocks and test stubs are also in place. No compilation breakage.

pkg/auth/identities/aws/assume_role.go (2)

278-285: Logout noop looks good.

Identity has no local artifacts; deferring cleanup to provider/manager is appropriate.


193-197: Environment() cannot access provider.Spec to resolve base_path—the architecture doesn't pass provider config to identity functions.

The review comment correctly identifies a consistency gap. While sso.py and saml.py properly call GetFilesBasePath(p.config) before NewAWSFileManager(), the identity functions (assume_role, permission_set, user) and SetupFiles/SetEnvironmentVariables in setup.go only receive providerName (string), not the full provider spec. They cannot access provider.Spec["files"]["base_path"] without structural changes.

This is a real problem: if a provider configures a custom files.base_path, the paths used in SetupFiles() (write) won't match where Environment() reads env vars, and won't match the display paths shown to users.

The fix requires either:

  • Passing the provider object through the identity call chain, or
  • Looking up the provider spec by name from an auth manager registry
pkg/auth/providers/aws/saml.go (1)

373-390: Provider logout looks good.

Uses provider-scoped base_path and joins ErrLogoutFailed on failure.

pkg/auth/hooks_test.go (2)

51-61: Stub methods look good.

Satisfies new AuthManager methods; simple no-op behavior suits these unit tests.


1-166: The review comment asks for cmd-level tests that contradict the stated coding guidelines.

The original comment references a non-existent performLogoutAll function (the actual function is performInteractiveLogout) and requests unit tests for cmd-level wrapper functions. However, the coding guideline explicitly states "Place business logic in pkg rather than in cmd." The logout functions in cmd/auth_logout.go are thin orchestration wrappers that delegate to pkg/auth methods (Logout, LogoutProvider, LogoutAll). Business logic testing belongs at the package level, where pkg/auth/manager_logout_test.go already exists.

Cmd-level integration tests (via tests/ fixtures) would validate the CLI flow end-to-end, but unit-level table-driven tests belong at the package level where the actual logout business logic is tested—not in cmd.

Likely an incorrect or invalid review comment.

cmd/auth_logout.go (1)

39-74: This review comment is incorrect. The version command's robustness for broken configs is ensured by root.go's PersistentPreRun logic (lines 94-103), not by auth_logout.go.

When atmos --version or atmos version runs, it executes within PersistentPreRun before any subcommand. That logic gracefully handles missing config files via cfg.NotFound checks. The auth_logout.go subcommand only runs if explicitly called and cannot affect the version command's execution path. Its error-handling pattern is consistent with other subcommands like auth_login and auth_validate.

Likely an incorrect or invalid review comment.

pkg/auth/manager.go (1)

751-760: Idempotent logout issue is real, but suggested fix won't work as written.

The core concern is valid: go-keyring's Delete does not guarantee an idempotent/no-error result for missing entries — it forwards the underlying backend's behavior. The current code fails logout when credentials don't exist, breaking idempotency.

However, the suggested diff checks for sentinels that don't exist in the codebase (ErrCredentialNotFound) or won't be returned by go-keyring (os.ErrNotExist). The package does not normalize all backends to one specific not-found error, so the approach won't work reliably.

To fix correctly:

  1. Verify what specific error go-keyring actually returns on your platform(s) when deleting missing entries
  2. Either wrap Delete to detect that error, treat all Delete errors as non-fatal (log only), or check existence first
  3. Ensure logout succeeds when there's nothing to remove

@codecov
Copy link

codecov bot commented Oct 17, 2025

Codecov Report

❌ Patch coverage is 71.61572% with 195 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.57%. Comparing base (7378e73) to head (8ac86aa).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
cmd/auth_logout.go 60.00% 92 Missing and 2 partials ⚠️
pkg/auth/cloud/aws/files.go 63.63% 23 Missing and 9 partials ⚠️
cmd/cmd_utils.go 0.00% 17 Missing ⚠️
pkg/auth/manager.go 91.25% 10 Missing and 6 partials ⚠️
pkg/auth/identities/aws/user.go 52.63% 5 Missing and 4 partials ⚠️
pkg/auth/providers/aws/saml.go 70.96% 6 Missing and 3 partials ⚠️
pkg/auth/providers/aws/sso.go 70.96% 6 Missing and 3 partials ⚠️
pkg/auth/credentials/store.go 64.28% 5 Missing ⚠️
pkg/auth/identities/aws/assume_role.go 81.81% 0 Missing and 2 partials ⚠️
pkg/auth/identities/aws/permission_set.go 81.81% 0 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1656      +/-   ##
==========================================
+ Coverage   66.43%   66.57%   +0.13%     
==========================================
  Files         357      359       +2     
  Lines       41126    41780     +654     
==========================================
+ Hits        27322    27814     +492     
- Misses      11768    11911     +143     
- Partials     2036     2055      +19     
Flag Coverage Δ
unittests 66.57% <71.61%> (+0.13%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
errors/errors.go 100.00% <ø> (ø)
pkg/auth/cloud/aws/env.go 93.18% <100.00%> (+1.07%) ⬆️
pkg/auth/cloud/aws/setup.go 43.75% <100.00%> (ø)
pkg/auth/cloud/aws/spec.go 100.00% <100.00%> (ø)
pkg/auth/providers/github/oidc.go 66.90% <100.00%> (+2.02%) ⬆️
pkg/config/cache.go 74.49% <ø> (ø)
pkg/auth/identities/aws/assume_role.go 86.24% <81.81%> (+0.60%) ⬆️
pkg/auth/identities/aws/permission_set.go 55.30% <81.81%> (+2.09%) ⬆️
pkg/auth/credentials/store.go 80.00% <64.28%> (+14.78%) ⬆️
pkg/auth/identities/aws/user.go 63.59% <52.63%> (-0.69%) ⬇️
... and 6 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Made several code quality improvements to auth logout implementation:

1. Performance Tracking:
   - Added perf.Track to executeAuthLogoutCommand in cmd/auth_logout.go
   - Added perf.Track to GetFilesBasePath in pkg/auth/cloud/aws/spec.go
   - Ensures performance monitoring for auth logout operations

2. Dead Code Removal:
   - Removed ErrLogoutNotSupported from errors/errors.go (never used)
   - All providers implement Logout, no concept of unsupported logout exists

3. Environment Variable Removal:
   - Removed ATMOS_AWS_FILES_BASE_PATH env var support per requirements
   - Only spec.files.base_path configuration is supported now
   - Removed viper import from pkg/auth/cloud/aws/files.go
   - Updated documentation to remove env var references

4. Documentation Updates:
   - Updated PRD to remove env var from precedence
   - Updated CLI docs to remove env var example and precedence
   - Simplified configuration to: spec config > default

Changes maintain backward compatibility - default behavior unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add ErrLogoutNotSupported (exit 0) and ErrLogoutNotImplemented (exit non-zero)
- GitHub OIDC returns ErrLogoutNotSupported (no local storage to clean)
- Manager treats ErrLogoutNotSupported as success
- Fix duplicate identity.Logout calls with identityLogoutCalled flag
- Add resolveProviderForIdentity for transitive Via chain resolution
- Update LogoutProvider to find identities transitively
- Add comprehensive tests (79.5% coverage in pkg/auth)
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/auth/cloud/aws/files.go (1)

223-236: Preserve error cause when cleanup fails; resolve absolute path before deletion.

  • Wrap with the sentinel using errors.Join to keep the root cause.
  • Use filepath.Abs before RemoveAll (safety, logs clearer).
 func (m *AWSFileManager) Cleanup(providerName string) error {
-    providerDir := filepath.Join(m.baseDir, providerName)
+    providerDir := filepath.Join(m.baseDir, providerName)
+    if abs, err := filepath.Abs(providerDir); err == nil {
+        providerDir = abs
+    }
 
-    if err := os.RemoveAll(providerDir); err != nil {
-        // If directory doesn't exist, that's not an error (already cleaned up).
-        if os.IsNotExist(err) {
-            return nil
-        }
-        errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, providerDir, "failed to cleanup AWS files")
-        return ErrCleanupAWSFiles
-    }
+    if err := os.RemoveAll(providerDir); err != nil {
+        if os.IsNotExist(err) {
+            return nil
+        }
+        errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, providerDir, "failed to cleanup AWS files")
+        return errors.Join(ErrCleanupAWSFiles, err)
+    }
     return nil
 }
 
 func (m *AWSFileManager) CleanupAll() error {
-    if err := os.RemoveAll(m.baseDir); err != nil {
+    base := m.baseDir
+    if abs, err := filepath.Abs(base); err == nil {
+        base = abs
+    }
+    if err := os.RemoveAll(base); err != nil {
         // If directory doesn't exist, that's not an error (already cleaned up).
         if os.IsNotExist(err) {
             return nil
         }
-        errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, m.baseDir, "failed to cleanup all AWS files")
-        return ErrCleanupAWSFiles
+        errUtils.CheckErrorAndPrint(ErrCleanupAWSFiles, base, "failed to cleanup all AWS files")
+        return errors.Join(ErrCleanupAWSFiles, err)
     }
     return nil
 }

As per coding guidelines.

Also applies to: 239-251

♻️ Duplicate comments (1)
pkg/auth/manager.go (1)

780-794: Nice: duplicate Identity.Logout on fallback chains is now guarded.

The identityLogoutCalled flag prevents double cleanup when chain == [identityName]. Thanks for addressing the earlier review.

Also applies to: 797-810

🧹 Nitpick comments (12)
docs/prd/auth-logout.md (2)

468-482: Fix error-wrapping example: only one %w allowed in fmt.Errorf.

The snippet uses two %w. Go permits at most one. Suggest joining the sentinel with the cause.

Replace the example with:

-errs = append(errs, fmt.Errorf("%w: keyring deletion failed: %w", 
-    ErrLogoutFailed, err))
+errs = append(errs, errors.Join(
+    ErrLogoutFailed,
+    fmt.Errorf("keyring deletion failed: %v", err),
+))

As per coding guidelines.


148-156: Add language to fenced code blocks to satisfy markdownlint.

Mark these output blocks as text.

-```
+```text
 ? Choose what to logout from:
   ❯ Identity: dev-admin
   ...
-```
+```text
⚠️  Important: This command only removes locally cached credentials.
...

Also applies to: 629-640

website/docs/cli/commands/auth/logout.mdx (1)

41-58: Specify languages on fenced code blocks (lint).

Add “text” for outputs to satisfy MD040 and improve rendering.

Example:

-```
+```text
Logging out from identity: dev-admin
...

Repeat for the listed blocks.

Also applies to: 91-98, 108-119, 188-205, 248-255, 263-272, 278-281, 296-299

cmd/auth_logout.go (3)

237-239: Graceful cancel in interactive mode (Ctrl+C).

Exit cleanly instead of surfacing an error.

- if err := form.Run(); err != nil {
-     return err
- }
+ if err := form.Run(); err != nil {
+     if errors.Is(err, context.Canceled) {
+         u.PrintfMessageToTUI("Canceled.\n")
+         return nil
+     }
+     return err
+ }

As per coding guidelines.


79-132: Add perf tracking to critical helpers.

Track time in helper paths too.

 func performIdentityLogout(ctx context.Context, authManager auth.AuthManager, identityName string, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performIdentityLogout")()
+
     // Validate identity exists.
 func performProviderLogout(ctx context.Context, authManager auth.AuthManager, providerName string, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performProviderLogout")()
 func performInteractiveLogout(ctx context.Context, authManager auth.AuthManager, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performInteractiveLogout")()
 func performLogoutAll(ctx context.Context, authManager auth.AuthManager, dryRun bool) error {
+    defer perf.Track(nil, "cmd.AuthLogout.performLogoutAll")()

As per coding guidelines.

Also applies to: 134-175, 177-252, 254-290


35-38: Replace unrelated arg completion.

ComponentsArgCompletion is not relevant here; it may suggest component names. Either drop it or implement identity completion.

- ValidArgsFunction:  ComponentsArgCompletion,
+ // TODO: implement identity completion (ListIdentities) and provider flag completion.
+ // ValidArgsFunction: identityArgCompletion,

Optionally, register provider flag completion in init(). Want a patch? Based on learnings.

pkg/auth/manager_logout_test.go (2)

226-263: Avoid brittle Times() expectations for provider cleanup.

Current test expects provider cleanup called 3x (per identity + once more). Provider cleanup should typically run once per provider. Either assert 1 call or use AnyTimes to avoid binding tests to internal call order.

- provider.EXPECT().Logout(gomock.Any()).Return(nil).Times(3)
+ provider.EXPECT().Logout(gomock.Any()).Return(nil).Times(1)

If manager intentionally calls provider cleanup per identity, document it in a comment.


16-25: Remove unused fields or assert them.

checkCalls/expectedCalls are never used. Either drop them or add assertions.

-    checkCalls    bool
-    expectedCalls int
+    // Add explicit call-count assertions or remove these fields.
pkg/auth/cloud/aws/files.go (2)

10-10: Use internal homedir utilities for consistency.

Prefer pkg/config/homedir over external go-homedir.

- homedir "github.com/mitchellh/go-homedir"
+ homedir "github.com/cloudposse/atmos/pkg/config/homedir"

Based on learnings.


49-66: Consider validating/normalizing baseDir once (abs path).

Optional: call filepath.Abs on baseDir post expansion to standardize paths across platforms (logging and deletion).

pkg/auth/manager.go (2)

334-360: Avoid hard-coding ~/.aws/atmos; fall back to default file manager for portability.

On error with a configured base_path, return the default manager’s display path (Windows-safe) before hard-coding a POSIX path.

 func (m *manager) GetFilesDisplayPath(providerName string) string {
   defer perf.Track(nil, "auth.Manager.GetFilesDisplayPath")()
@@
   // Create file manager to get display path.
-  fileManager, err := awsCloud.NewAWSFileManager(basePath)
-  if err != nil {
-    return "~/.aws/atmos"
-  }
+  fileManager, err := awsCloud.NewAWSFileManager(basePath)
+  if err != nil {
+    log.Debug("Failed to init AWSFileManager with configured base path; falling back to default.", "provider", providerName, "error", err)
+    if fm2, err2 := awsCloud.NewAWSFileManager(""); err2 == nil {
+      return fm2.GetDisplayPath()
+    }
+    return "~/.aws/atmos"
+  }
 
   return fileManager.GetDisplayPath()
 }

928-951: LogoutAll: de-dup provider cleanup across identities.

Same duplicate provider.Logout concern as above; consider the same context flag approach to skip per‑identity provider cleanup during LogoutAll, then optionally perform one cleanup per provider post‑loop.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 57677f7 and 75c3c17.

📒 Files selected for processing (9)
  • cmd/auth_logout.go (1 hunks)
  • docs/prd/auth-logout.md (1 hunks)
  • errors/errors.go (1 hunks)
  • pkg/auth/cloud/aws/files.go (4 hunks)
  • pkg/auth/cloud/aws/spec.go (1 hunks)
  • pkg/auth/manager.go (3 hunks)
  • pkg/auth/manager_logout_test.go (1 hunks)
  • pkg/auth/providers/github/oidc.go (1 hunks)
  • website/docs/cli/commands/auth/logout.mdx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/auth/providers/github/oidc.go
  • errors/errors.go
  • pkg/auth/cloud/aws/spec.go
🧰 Additional context used
📓 Path-based instructions (9)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/auth/manager_logout_test.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/manager.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven unit tests for pure functions and focus on behavior; co-locate tests; target >80% coverage for pkg/ and internal/exec/.
Always use t.Skipf() with a clear reason; never use t.Skip() or t.Skipf without a reason.

Files:

  • pkg/auth/manager_logout_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods; applies to single-line, multi-line, inline, and documentation comments (golangci-lint godot).
Group imports into three sections (stdlib, 3rd-party, Atmos), separated by blank lines; sort alphabetically within each group; preserve existing aliases.
Configuration loading must use Viper with precedence CLI → ENV → files → defaults; bind config name atmos and add path, AutomaticEnv, and ATMOS prefix.
All errors must be wrapped using static errors (defined in errors/errors.go); use errors.Join for multiple errors; fmt.Errorf with %w for context; use errors.Is for checks; never compare error strings.
Distinguish structured logging from UI output: UI prompts/status/errors to stderr; data/results to stdout; never use logging for UI.
Most text UI must go to stderr; only data/results to stdout; prefer utils.PrintfMessageToTUI for UI messages.
All new configurations must support Go templating using existing utilities and available template functions.
Prefer SDKs over external binaries for cross-platform support; use filepath/os/runtime for portability.
For non-standard execution paths, capture telemetry via telemetry.CaptureCmd or telemetry.CaptureCmdString without user data.
80% minimum coverage on new/changed lines and include unit tests for new features; add integration tests for CLI using tests/ fixtures.
Always bind environment variables with viper.BindEnv and provide ATMOS_ alternatives for every env var.
Use structured logging with levels (Fatal>Error>Warn>Debug>Trace); avoid string interpolation and ensure logging does not affect execution.
Prefer re...

Files:

  • pkg/auth/manager_logout_test.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/manager.go
  • cmd/auth_logout.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for packages live under pkg/ alongside implementation files.

Files:

  • pkg/auth/manager_logout_test.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Add defer perf.Track() to all public functions and critical private functions; include a blank line after the call; use package-prefixed names; pass atmosConfig when present, else nil.

Files:

  • pkg/auth/cloud/aws/files.go
  • pkg/auth/manager.go
  • cmd/auth_logout.go
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate

cmd/**/*.go: Use utils.PrintfMarkdown() to render embedded markdown content for CLI command help/examples.
One Cobra command per file in cmd/; keep files focused and small.

Files:

  • cmd/auth_logout.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases

Before committing documentation/site changes, run npm run build in website/ and fix errors, broken links, and missing images.

Files:

  • website/docs/cli/commands/auth/logout.mdx
website/docs/cli/commands/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Document all new commands/flags/parameters in Docusaurus under website/docs/cli/commands/, using definition lists for args/flags and the prescribed frontmatter and sections.

Files:

  • website/docs/cli/commands/auth/logout.mdx
website/docs/**

📄 CodeRabbit inference engine (CLAUDE.md)

website/docs/**: After modifying any docs under website/docs/, build the website (npm run build) and ensure no errors.
Document user-facing template functions in the website if applicable.

Files:

  • website/docs/cli/commands/auth/logout.mdx
🧠 Learnings (11)
📚 Learning: 2025-10-18T03:22:41.749Z
Learnt from: osterman
PR: cloudposse/atmos#1656
File: pkg/auth/identities/aws/user.go:365-372
Timestamp: 2025-10-18T03:22:41.749Z
Learning: In pkg/auth/identities/aws/user.go, the Logout method intentionally calls fileManager.Cleanup("aws-user") to remove the entire provider directory. This is correct behavior because all aws-user identities share the same provider authentication state, so logging out one aws-user identity should log out all of them by removing the shared provider credentials.

Applied to files:

  • pkg/auth/manager_logout_test.go
  • pkg/auth/cloud/aws/files.go
  • pkg/auth/manager.go
  • website/docs/cli/commands/auth/logout.mdx
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
PR: cloudposse/atmos#1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
PR: cloudposse/atmos#1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/*.go : Always bind environment variables with viper.BindEnv and provide ATMOS_ alternatives for every env var.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/*.go : Configuration loading must use Viper with precedence CLI → ENV → files → defaults; bind config name atmos and add path, AutomaticEnv, and ATMOS prefix.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-09-29T15:47:10.908Z
Learnt from: aknysh
PR: cloudposse/atmos#1540
File: internal/exec/terraform_cli_args_utils.go:64-73
Timestamp: 2025-09-29T15:47:10.908Z
Learning: In the Atmos codebase, viper.BindEnv is required for CLI commands in the cmd/ package, but internal utilities can use os.Getenv directly when parsing environment variables for business logic purposes. The requirement to use viper is specific to the CLI interface layer, not all environment variable access throughout the codebase.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
PR: cloudposse/atmos#727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
PR: cloudposse/atmos#740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-09-23T04:43:31.857Z
Learnt from: osterman
PR: cloudposse/atmos#1430
File: pkg/config/config.go:98-107
Timestamp: 2025-09-23T04:43:31.857Z
Learning: In the Atmos codebase, NO_PAGER environment variable handling is intentionally kept as direct os.Getenv() access in pkg/config/config.go rather than using Viper binding, because adding no_pager to the config file would be confusing for users. This is an acknowledged exception to the normal Viper binding pattern for environment variables.

Applied to files:

  • pkg/auth/cloud/aws/files.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
PR: cloudposse/atmos#1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/auth/manager.go
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/!(*_test).go : Add `defer perf.Track()` to all public functions and critical private functions; include a blank line after the call; use package-prefixed names; pass atmosConfig when present, else nil.

Applied to files:

  • cmd/auth_logout.go
🧬 Code graph analysis (4)
pkg/auth/manager_logout_test.go (4)
pkg/auth/types/mock_interfaces.go (6)
  • MockCredentialStore (515-518)
  • MockProvider (17-20)
  • MockIdentity (140-143)
  • NewMockCredentialStore (526-530)
  • NewMockProvider (28-32)
  • NewMockIdentity (151-155)
pkg/schema/schema_auth.go (2)
  • AuthConfig (4-8)
  • IdentityVia (42-45)
pkg/auth/types/interfaces.go (2)
  • Provider (13-37)
  • Identity (40-64)
errors/errors.go (5)
  • ErrIdentityNotInConfig (381-381)
  • ErrPartialLogout (375-375)
  • ErrLogoutFailed (374-374)
  • ErrProviderNotInConfig (382-382)
  • ErrLogoutNotSupported (376-376)
pkg/auth/cloud/aws/files.go (2)
pkg/config/homedir/homedir.go (2)
  • Expand (68-87)
  • Dir (36-63)
errors/error_funcs.go (1)
  • CheckErrorAndPrint (29-52)
pkg/auth/manager.go (5)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/auth/cloud/aws/files.go (1)
  • NewAWSFileManager (46-68)
pkg/auth/cloud/aws/spec.go (1)
  • GetFilesBasePath (14-32)
errors/errors.go (8)
  • ErrIdentityNotInConfig (381-381)
  • ErrKeyringDeletion (378-378)
  • ErrLogoutNotSupported (376-376)
  • ErrProviderLogout (379-379)
  • ErrIdentityLogout (380-380)
  • ErrPartialLogout (375-375)
  • ErrLogoutFailed (374-374)
  • ErrProviderNotInConfig (382-382)
pkg/auth/types/interfaces.go (2)
  • Provider (13-37)
  • Identity (40-64)
cmd/auth_logout.go (7)
cmd/cmd_utils.go (1)
  • ComponentsArgCompletion (768-790)
pkg/config/config.go (1)
  • InitCliConfig (25-62)
errors/errors.go (6)
  • ErrFailedToInitializeAtmosConfig (117-117)
  • ErrAuthManager (334-334)
  • ErrIdentityNotInConfig (381-381)
  • ErrPartialLogout (375-375)
  • ErrProviderNotInConfig (382-382)
  • ErrInvalidLogoutOption (383-383)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/auth/types/interfaces.go (1)
  • AuthManager (67-121)
pkg/utils/log_utils.go (1)
  • PrintfMessageToTUI (33-35)
internal/tui/utils/utils.go (1)
  • NewAtmosHuhTheme (85-93)
🪛 LanguageTool
docs/prd/auth-logout.md

[typographical] ~57-~57: Consider using typographic quotation marks here.
Context: ...elet Huh for styled selection - Allow "All identities" option - Apply Atmos theme to prompts...

(EN_QUOTES)


[grammar] ~661-~661: Ensure spelling is correct
Context: ...lement styled output with Charmbracelet lipgloss - [ ] Add progress indicators for multi-st...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[typographical] ~728-~728: Consider using typographic quotation marks here.
Context: ...upport --all flag or just interactive "All identities" option? Decision: Use interactive ...

(EN_QUOTES)

website/docs/cli/commands/auth/logout.mdx

[style] ~18-~18: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ing Local Credentials Only This command only removes **credentials stored on your lo...

(ADVERB_REPETITION_PREMIUM)


[grammar] ~89-~89: Ensure spelling is correct
Context: ...s an interactive menu to choose what to logout from: ``` ? Choose what to logout from...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~219-~219: Ensure spelling is correct
Context: ...o completely end your session and fully logout: 1. Run atmos auth logout to remove local ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~403-~403: Ensure spelling is correct
Context: ...validate ``` ## Best Practices ### 1. Logout When Switching Contexts When switching...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~405-~405: Ensure spelling is correct
Context: ...n different identities or environments, logout first to ensure clean state: ```shell ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
docs/prd/auth-logout.md

148-148: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


629-629: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Summary
🔇 Additional comments (4)
docs/prd/auth-logout.md (1)

746-751: Docs/code mismatch on partial success exit status.

Spec says exit 0 on partial success. CLI currently treats provider/all partial errors as failures. See cmd/auth_logout.go error handling in performProviderLogout/performLogoutAll.

Want me to align the CLI to return 0 on ErrPartialLogout? Based on learnings.

pkg/auth/manager.go (3)

12-12: Import alias usage looks good.

aws file-manager helpers are used below; alias keeps call sites clear.


825-866: Both concerns already addressed in the codebase; review comment needs correction.

The AWS pseudo-provider handling is fully implemented—aws.IsStandaloneAWSUserChain() exists, GetProviderForIdentity() returns "aws-user" for standalone users (line 328–329), and LogoutProvider has fallback logic to handle identities as pseudo-providers (line 779–780).

Regarding perf tracking: all public methods in the file follow the pattern of defer perf.Track() at entry, but private helpers are not systematically tracked—only the public methods. Since resolveProviderForIdentity is a private helper called exclusively from the already-tracked LogoutProvider, adding separate tracking here would deviate from the established pattern and likely add noise without meaningful visibility gains.

The original concern about aws-user appears to misread the codebase; the requirement is already satisfied.

Likely an incorrect or invalid review comment.


729-823: The review comment's error handling suggestion is incorrect and won't work as written.

zalando/go-keyring's Delete method returns nil for missing keys (most backends treat delete-nonexistent as success). The current code wraps keyring errors with ErrCredentialStore, never ErrNoCredentialsFound. The suggestion to check errors.Is(err, errUtils.ErrNoCredentialsFound) will never match—Delete doesn't return that error, and semantically it's used for Retrieve failures, not deletions.

Additionally, the current Delete implementation already handles missing keys gracefully (keyring library returns nil), so the special case check is unnecessary.

The chain cleanup logic (Step 4) is a separate concern that may have merit based on the learnings about aws-user identities, but it shouldn't be bundled with a flawed error-handling refactor.

Likely an incorrect or invalid review comment.

- Add ErrPartialLogout handling to cmd/auth_logout.go (treat as success/exit 0)
- Fix N+1 provider.Logout calls in LogoutProvider using context flag
- Treat keyring.ErrNotFound as success in credentialStore.Delete
- Fix test map types to use types.Provider and types.Identity
- Update test expectations to expect Times(1) for provider operations
- Add comprehensive test for LogoutProvider with failures
- Test coverage increased from 79.6% to 80.8%
…tials

- Add CleanupIdentity() method to AWSFileManager
- Remove only specific identity's sections from shared INI files
- Prevent deletion of other identities' credentials when logging out one identity
- Add removeIniSection() helper to safely remove INI sections
- Update aws-user identity to use CleanupIdentity instead of Cleanup

This fixes the critical issue where logging out one aws-user identity would
delete credentials for all identities using the same provider.
…ntials

- Delete now treats keyring.ErrNotFound as success (idempotent)
- Updated test to assert.NoError instead of assert.Error
- Added test for deleting already-deleted credential (idempotent behavior)
- Already have 2025-10-17-auth-logout-feature.md
- Shouldn't have created a duplicate
- Reframe problem: cloud tooling doesn't make logout easy
- Focus on credential sprawl across AWS, Azure, GCP
- Emphasize manual cleanup burden and security risks
- Position Atmos logout as solving general cloud tooling gap
- Remove implication that Atmos previously lacked logout
- Add context about cloud tooling not making logout easy
- Mention credential sprawl across AWS, Azure, GCP
- Frame logout as making cleanup explicit and comprehensive
- Maintain existing detailed documentation structure
- Keep intro concise and focused on what the command does
- Add 'The Problem' section below intro
- Explains credential sprawl and lack of easy logout in cloud tooling
- Positions Atmos logout as the solution
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 475404d and f2c44c2.

📒 Files selected for processing (3)
  • NOTICE (2 hunks)
  • website/blog/2025-10-17-auth-logout-feature.md (1 hunks)
  • website/docs/cli/commands/auth/logout.mdx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases

Always build the website (npm run build) after documentation changes to ensure no errors, broken links, or missing assets.

Files:

  • website/docs/cli/commands/auth/logout.mdx
  • website/blog/2025-10-17-auth-logout-feature.md
website/docs/cli/commands/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

All new commands/flags/parameters must have Docusaurus documentation under website/docs/cli/commands//.mdx using the prescribed frontmatter and sections.

Files:

  • website/docs/cli/commands/auth/logout.mdx
website/**/{*.md,*.mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use definition lists

for arguments and flags in docs instead of tables.

Files:

  • website/docs/cli/commands/auth/logout.mdx
  • website/blog/2025-10-17-auth-logout-feature.md
website/blog/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

website/blog/*.md: PRs labeled minor or major must include a blog post in website/blog/YYYY-MM-DD-feature-name.md with required frontmatter, tags, and truncate marker.
Use appropriate audience tags (feature/enhancement/bugfix or contributors) and relevant secondary tags in blog posts.

Files:

  • website/blog/2025-10-17-auth-logout-feature.md
🪛 LanguageTool
website/docs/cli/commands/auth/logout.mdx

[style] ~18-~18: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ing Local Credentials Only This command only removes **credentials stored on your lo...

(ADVERB_REPETITION_PREMIUM)


[grammar] ~109-~109: Ensure spelling is correct
Context: ...s an interactive menu to choose what to logout from: ``` ? Choose what to logout from...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~239-~239: Ensure spelling is correct
Context: ...o completely end your session and fully logout: 1. Run atmos auth logout to remove local ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~423-~423: Ensure spelling is correct
Context: ...validate ``` ## Best Practices ### 1. Logout When Switching Contexts When switching...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~425-~425: Ensure spelling is correct
Context: ...n different identities or environments, logout first to ensure clean state: ```shell ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

website/blog/2025-10-17-auth-logout-feature.md

[grammar] ~182-~182: Please add a punctuation mark at the end of paragraph.
Context: ...he browser session 4. Close all browser windows The command displays this warning afte...

(PUNCTUATION_PARAGRAPH_END)


[grammar] ~186-~186: Ensure spelling is correct
Context: ...o ensure you don't forget. ### When to Logout **Logout at the end of your work session:*...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~311-~311: Please add a punctuation mark at the end of paragraph.
Context: ...ath` package for platform-specific path separators ### Error Handling Following Atmos er...

(PUNCTUATION_PARAGRAPH_END)


[grammar] ~320-~320: Please add a punctuation mark at the end of paragraph.
Context: ...on-fatal errors - Reports all errors at completion ### Interface Extensions The logout f...

(PUNCTUATION_PARAGRAPH_END)

🪛 markdownlint-cli2 (0.18.1)
website/blog/2025-10-17-auth-logout-feature.md

44-44: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


71-71: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


92-92: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


113-113: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


132-132: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


153-153: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


213-213: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Build (windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Lint (golangci)
  • GitHub Check: Review Dependency Licenses
  • GitHub Check: website-deploy-preview
  • GitHub Check: autofix
  • GitHub Check: Summary
🔇 Additional comments (3)
website/docs/cli/commands/auth/logout.mdx (1)

1-469: Documentation structure and content look solid.

The mdx file follows all guidelines: proper frontmatter, definition lists for args/flags, comprehensive sections covering usage, examples, security, troubleshooting, and advanced config. Content is consistent with the blog post but appropriately tailored for reference documentation.

Per coding guidelines, please confirm that you ran npm run build in the website/ directory to validate the Docusaurus build, check for broken links, and ensure all components render correctly.

NOTICE (2)

677-679: Looks good!

The go-difflib dependency entry is correctly formatted and placed in the BSD-3-Clause section. This is a common testing utility, typically used by testify for assertion diffs.


1479-1481: Verified—NOTICE entry is correct.

Both license URLs are accessible and the testify entry is properly formatted with the correct version tag. No issues found.

- Tests were calling Reset() on mitchellh/go-homedir
- Production code uses our forked pkg/config/homedir
- This caused cache to not be cleared properly between test runs
- Update both setup_test.go and files_test.go to use our fork
- Tests now pass reliably when run multiple times
- Add comprehensive Reset() tests to homedir package
- Add forbidigo rule to prevent importing github.com/mitchellh/go-homedir
- Direct developers to use our forked pkg/config/homedir instead
- Prevents future test flakiness from using wrong homedir package
- Config verified with golangci-lint config verify
Blog post fixes (2025-10-17-auth-logout-feature.md):
- Add shell language specifiers to 7 code blocks (lines 44, 71, 92, 113, 132, 153, 213)
- Add missing periods to list items (lines 182, 311, 320)

Homedir test fixes (pkg/config/homedir/homedir_test.go):
- Add Reset() calls to TestDir and TestExpand to prevent cross-test interference
- Fix TestExpand expected path construction (remove trailing separator)
- Tests now pass reliably when run multiple times
@aknysh aknysh merged commit c4a7ab7 into main Oct 22, 2025
55 checks passed
@aknysh aknysh deleted the feature/dev-3705-implement-atmos-auth-logout-to-remove-local-credential-store branch October 22, 2025 01:09
@github-actions
Copy link

These changes were released in v1.196.0-rc.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants