cloudsmith-cli 1.29.0__tar.gz → 1.30.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. {cloudsmith_cli-1.29.0/cloudsmith_cli.egg-info → cloudsmith_cli-1.30.0}/PKG-INFO +15 -27
  2. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/README.md +12 -25
  3. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/command.py +43 -1
  4. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/auth.py +11 -10
  5. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/manage.py +71 -8
  6. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/terraform.py +12 -11
  7. cloudsmith_cli-1.30.0/cloudsmith_cli/cli/commands/domains.py +305 -0
  8. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/download.py +7 -0
  9. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/login.py +76 -6
  10. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/logout.py +7 -7
  11. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/main.py +3 -0
  12. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/deny.py +2 -1
  13. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/license.py +3 -2
  14. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/vulnerability.py +3 -3
  15. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/repos.py +2 -1
  16. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/tokens.py +20 -24
  17. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/update.py +2 -2
  18. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/upstream.py +2 -1
  19. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/whoami.py +7 -7
  20. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/config.py +69 -9
  21. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/decorators.py +122 -32
  22. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/exceptions.py +16 -6
  23. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/saml.py +0 -24
  24. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/utils.py +3 -2
  25. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/validators.py +5 -5
  26. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/webserver.py +5 -4
  27. cloudsmith_cli-1.30.0/cloudsmith_cli/conftest.py +83 -0
  28. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/exceptions.py +5 -0
  29. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/files.py +20 -8
  30. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/init.py +3 -1
  31. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/orgs.py +5 -9
  32. cloudsmith_cli-1.30.0/cloudsmith_cli/core/api/workspaces.py +22 -0
  33. cloudsmith_cli-1.30.0/cloudsmith_cli/core/certificate_errors.py +80 -0
  34. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/config.py +32 -19
  35. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/models.py +2 -1
  36. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/aws.py +20 -2
  37. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/gcp.py +8 -1
  38. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/keyring_provider.py +1 -0
  39. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/download.py +1 -1
  40. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/keyring.py +4 -4
  41. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/server.py +6 -2
  42. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/session.py +91 -1
  43. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/sso.py +9 -9
  44. cloudsmith_cli-1.30.0/cloudsmith_cli/core/telemetry.py +841 -0
  45. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/update_check.py +26 -7
  46. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/utils.py +5 -0
  47. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/installer.py +26 -27
  48. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/runtime.py +4 -11
  49. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/common.py +27 -3
  50. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/installer.py +22 -25
  51. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/runtime.py +3 -10
  52. cloudsmith_cli-1.30.0/cloudsmith_cli/credential_helpers/domains.py +399 -0
  53. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/generic.py +4 -9
  54. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/launchers.py +25 -33
  55. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/installer.py +13 -22
  56. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/runtime.py +3 -10
  57. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/installer.py +5 -20
  58. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/runtime.py +28 -15
  59. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/terraformrc.py +1 -1
  60. cloudsmith_cli-1.30.0/cloudsmith_cli/data/VERSION +1 -0
  61. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/data/config.ini +11 -5
  62. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0/cloudsmith_cli.egg-info}/PKG-INFO +15 -27
  63. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/SOURCES.txt +4 -2
  64. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/requires.txt +2 -1
  65. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/pyproject.toml +2 -1
  66. cloudsmith_cli-1.29.0/cloudsmith_cli/cli/commands/domains.py +0 -304
  67. cloudsmith_cli-1.29.0/cloudsmith_cli/conftest.py +0 -16
  68. cloudsmith_cli-1.29.0/cloudsmith_cli/credential_helpers/custom_domains.py +0 -378
  69. cloudsmith_cli-1.29.0/cloudsmith_cli/credential_helpers/default_domains.py +0 -305
  70. cloudsmith_cli-1.29.0/cloudsmith_cli/data/VERSION +0 -1
  71. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/LICENSE +0 -0
  72. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/MANIFEST.in +0 -0
  73. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/__init__.py +0 -0
  74. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/__main__.py +0 -0
  75. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/__init__.py +0 -0
  76. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/__init__.py +0 -0
  77. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/check.py +0 -0
  78. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/copy.py +0 -0
  79. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/__init__.py +0 -0
  80. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/cargo.py +0 -0
  81. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/docker.py +0 -0
  82. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/generic.py +0 -0
  83. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/pnpm.py +0 -0
  84. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/delete.py +0 -0
  85. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/dependencies.py +0 -0
  86. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/docs.py +0 -0
  87. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/entitlements.py +0 -0
  88. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/help_.py +0 -0
  89. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/list_.py +0 -0
  90. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/mcp.py +0 -0
  91. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metadata.py +0 -0
  92. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
  93. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
  94. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/entitlements.py +0 -0
  95. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
  96. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/move.py +0 -0
  97. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/__init__.py +0 -0
  98. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
  99. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/push.py +0 -0
  100. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quarantine.py +0 -0
  101. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
  102. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
  103. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
  104. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
  105. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/registry.py +0 -0
  106. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/resync.py +0 -0
  107. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/status.py +0 -0
  108. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/tags.py +0 -0
  109. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/vulnerabilities.py +0 -0
  110. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/dsc_parser.py +0 -0
  111. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/metadata_common.py +0 -0
  112. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/table.py +0 -0
  113. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/types.py +0 -0
  114. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/__init__.py +0 -0
  115. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/__init__.py +0 -0
  116. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/distros.py +0 -0
  117. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/entitlements.py +0 -0
  118. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/metadata.py +0 -0
  119. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/metrics.py +0 -0
  120. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/packages.py +0 -0
  121. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/quota.py +0 -0
  122. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/rates.py +0 -0
  123. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/repos.py +0 -0
  124. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/status.py +0 -0
  125. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/upstreams.py +0 -0
  126. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/user.py +0 -0
  127. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/v2.py +0 -0
  128. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/version.py +0 -0
  129. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/vulnerabilities.py +0 -0
  130. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/cache_utils.py +0 -0
  131. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/__init__.py +0 -0
  132. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/chain.py +0 -0
  133. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/__init__.py +0 -0
  134. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/cache.py +0 -0
  135. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +0 -0
  136. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +0 -0
  137. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/base.py +0 -0
  138. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +0 -0
  139. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/buildkite.py +0 -0
  140. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +0 -0
  141. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/generic.py +0 -0
  142. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +0 -0
  143. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +0 -0
  144. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/exchange.py +0 -0
  145. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/provider.py +0 -0
  146. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/__init__.py +0 -0
  147. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/cli_flag.py +0 -0
  148. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/credentials_file.py +0 -0
  149. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/env_var.py +0 -0
  150. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/oidc_provider.py +0 -0
  151. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/installation.py +0 -0
  152. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/macos_keychain.py +0 -0
  153. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/__init__.py +0 -0
  154. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/data.py +0 -0
  155. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/pagination.py +0 -0
  156. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/ratelimits.py +0 -0
  157. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/rest.py +0 -0
  158. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/self_update.py +0 -0
  159. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/version.py +0 -0
  160. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/__init__.py +0 -0
  161. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/backends.py +0 -0
  162. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/__init__.py +0 -0
  163. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/__init__.py +0 -0
  164. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/__init__.py +0 -0
  165. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/rc.py +0 -0
  166. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/__init__.py +0 -0
  167. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/data/credentials.ini +0 -0
  168. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/__init__.py +0 -0
  169. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_error.html +0 -0
  170. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_success.html +0 -0
  171. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_two_factor.html +0 -0
  172. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/wrapper.py +0 -0
  173. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
  174. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
  175. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/top_level.txt +0 -0
  176. {cloudsmith_cli-1.29.0 → cloudsmith_cli-1.30.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudsmith-cli
3
- Version: 1.29.0
3
+ Version: 1.30.0
4
4
  Summary: Cloudsmith Command-Line Interface (CLI)
5
5
  Author-email: Cloudsmith Ltd <support@cloudsmith.io>
6
6
  License-Expression: Apache-2.0
@@ -37,13 +37,14 @@ Requires-Dist: mcp==2.3.0
37
37
  Requires-Dist: pydantic-settings>=2.14.2
38
38
  Requires-Dist: PyJWT[crypto]>=2.13.0
39
39
  Requires-Dist: python-toon==0.2.0
40
- Requires-Dist: requests>=2.18.4
40
+ Requires-Dist: requests>=2.32.5
41
41
  Requires-Dist: requests_toolbelt>=1.0.0
42
42
  Requires-Dist: rich>=13.0.0
43
43
  Requires-Dist: semver>=2.7.9
44
44
  Requires-Dist: starlette>=1.3.1
45
45
  Requires-Dist: urllib3>=2.5
46
46
  Requires-Dist: tomlkit>=0.15.0
47
+ Requires-Dist: sentry-sdk<3,>=2
47
48
  Provides-Extra: aws
48
49
  Requires-Dist: boto3[crt]>=1.26.0; extra == "aws"
49
50
  Provides-Extra: gcp
@@ -102,8 +103,8 @@ The CLI currently supports the following commands (and sub-commands):
102
103
  - `entitlements`|`ents`: List entitlements for a repository.
103
104
  - `packages`: List packages for a repository. (Aliases `repos list`)
104
105
  - `repos`: List repositories for a namespace (owner).
105
- - `login`|`token`: Retrieve your API authentication token/key via login.
106
- - `logout`: Clear stored authentication credentials and SSO tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
106
+ - `login`|`token`: [DEPRECATED] Retrieve your API authentication token/key via login.
107
+ - `logout`: Clear stored authentication credentials and SAML tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
107
108
  - `metadata`: Manage arbitrary JSON metadata (SBOM, BuildInfo, custom) attached to a package.
108
109
  - `add`: Attach a new metadata entry to a package.
109
110
  - `list`|`ls`: List metadata entries for a package, or fetch a single entry by slug.
@@ -367,7 +368,7 @@ Both configuration files use the simple INI format, such as:
367
368
  api_key=1234567890abcdef1234567890abcdef
368
369
  ```
369
370
 
370
- Additionally, the CLI will store SSO access and refresh tokens in the system keyring
371
+ Additionally, the CLI will store SAML access and refresh tokens in the system keyring
371
372
  using the [`keyring`](https://github.com/jaraco/keyring) library.
372
373
 
373
374
 
@@ -378,8 +379,9 @@ See the [default config](https://raw.githubusercontent.com/cloudsmith-io/cloudsm
378
379
  You can specify the following configuration options:
379
380
 
380
381
  - `api_host`: The API host to connect to.
381
- - `api_proxy`: The API proxy to connect through.
382
- - `api_ssl_verify`: Whether or not to use SSL verification for requests.
382
+ - `proxy`: The proxy to connect through for all HTTP requests, including API, SAML, upload, download, MCP, update, credential helper, OIDC, and error report connections. Use `--proxy` or `CLOUDSMITH_PROXY` to set it for one command. The config key `api_proxy`, flag `--api-proxy`, and environment variable `CLOUDSMITH_API_PROXY` remain supported for compatibility. In config and environment variables, the new name takes precedence over the alias. Without `proxy`, the CLI uses the `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables. When `proxy` is set, it takes precedence over them.
383
+ - `ssl_verify`: Whether or not to verify SSL certificates for HTTPS requests, including API, SAML, uploads, downloads, and MCP (default: `true`). Use `CLOUDSMITH_SSL_VERIFY=1` to enable verification or `CLOUDSMITH_SSL_VERIFY=0` / `--without-ssl-verify` to disable it. Disabling verification is dangerous; prefer disabling only strict checks where possible. The config key `api_ssl_verify`, flag `--without-api-ssl-verify` / `-S`, and environment variable `CLOUDSMITH_WITHOUT_API_SSL_VERIFY` remain supported for compatibility. Command-line settings override environment variables, which override config; within the same source, the new spelling takes precedence.
384
+ - `ssl_verify_strict`: Whether or not to apply strict X.509 certificate verification (`VERIFY_X509_STRICT`, enabled by default on Python 3.13+). Set to `false` (or use `--without-ssl-verify-strict` / `CLOUDSMITH_SSL_VERIFY_STRICT=0`) if a TLS-intercepting proxy issues certificates that fail these checks. `CLOUDSMITH_SSL_VERIFY_STRICT=1` keeps strict verification enabled (the default). Certificates are still verified.
383
385
  - `api_user_agent`: The user agent to use for requests.
384
386
 
385
387
  ### Credentials (credentials.ini)
@@ -418,29 +420,15 @@ cloudsmith auth --owner example --no-browser
418
420
 
419
421
  #### Getting Your API Key
420
422
 
421
- You can retrieve your API key using the `cloudsmith login` command:
423
+ Get your API key from the Cloudsmith web app: click your user icon in the top right corner, then click **Personal API Keys**. See [API Key](https://docs.cloudsmith.com/accounts-and-teams/api-key) for more information. If you authenticated with `cloudsmith auth`, you can also use `cloudsmith tokens create` to create an API key.
422
424
 
423
- ```
424
- cloudsmith login
425
- Login: you@example.com
426
- Password:
427
- Repeat for confirmation:
428
- ```
429
-
430
- *Note:* Please ensure you use your email for the 'Login' prompt and not your user slug/identifier.
431
-
432
- The resulting output looks something like:
433
-
434
- ```
435
- Retrieving API token for 'you@example.com' ... OK
436
- Your API token is: 1234567890abcdef1234567890abcdef
437
- ```
438
-
439
- Once you have your API key you can then put this into your `credentials.ini`, use it as an environment variable `export CLOUDSMITH_API_KEY=your_key_here` or pass it to the CLI using the `-k your_key_here` flag.
425
+ Give your API key to the CLI in one of these ways:
440
426
 
441
- For convenience the CLI will ask you if you want to install the default configuration files, complete with your API key, if they don't already exist. Say 'y' or 'yes' to create the configuration files.
427
+ - Set the `CLOUDSMITH_API_KEY` environment variable: `export CLOUDSMITH_API_KEY=your_key_here`.
428
+ - Put the key into your `credentials.ini` file.
429
+ - Pass the key to the CLI with the `-k your_key_here` flag.
442
430
 
443
- If the configuration files already exist, you'll have to manually put the API key into the configuration files, but the CLI will print out their locations.
431
+ *Note:* The `cloudsmith login` command and its `cloudsmith token` alias are deprecated. They retrieve your API key with your email address and password, and they will stop working on November 20, 2026, when Cloudsmith disables username and password login. See the [Cloudsmith changelog](https://cloudsmith.com/changelog). After that, both commands fail with a message that explains how to get an API key instead.
444
432
 
445
433
 
446
434
  ## Uploading Packages
@@ -47,8 +47,8 @@ The CLI currently supports the following commands (and sub-commands):
47
47
  - `entitlements`|`ents`: List entitlements for a repository.
48
48
  - `packages`: List packages for a repository. (Aliases `repos list`)
49
49
  - `repos`: List repositories for a namespace (owner).
50
- - `login`|`token`: Retrieve your API authentication token/key via login.
51
- - `logout`: Clear stored authentication credentials and SSO tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
50
+ - `login`|`token`: [DEPRECATED] Retrieve your API authentication token/key via login.
51
+ - `logout`: Clear stored authentication credentials and SAML tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
52
52
  - `metadata`: Manage arbitrary JSON metadata (SBOM, BuildInfo, custom) attached to a package.
53
53
  - `add`: Attach a new metadata entry to a package.
54
54
  - `list`|`ls`: List metadata entries for a package, or fetch a single entry by slug.
@@ -312,7 +312,7 @@ Both configuration files use the simple INI format, such as:
312
312
  api_key=1234567890abcdef1234567890abcdef
313
313
  ```
314
314
 
315
- Additionally, the CLI will store SSO access and refresh tokens in the system keyring
315
+ Additionally, the CLI will store SAML access and refresh tokens in the system keyring
316
316
  using the [`keyring`](https://github.com/jaraco/keyring) library.
317
317
 
318
318
 
@@ -323,8 +323,9 @@ See the [default config](https://raw.githubusercontent.com/cloudsmith-io/cloudsm
323
323
  You can specify the following configuration options:
324
324
 
325
325
  - `api_host`: The API host to connect to.
326
- - `api_proxy`: The API proxy to connect through.
327
- - `api_ssl_verify`: Whether or not to use SSL verification for requests.
326
+ - `proxy`: The proxy to connect through for all HTTP requests, including API, SAML, upload, download, MCP, update, credential helper, OIDC, and error report connections. Use `--proxy` or `CLOUDSMITH_PROXY` to set it for one command. The config key `api_proxy`, flag `--api-proxy`, and environment variable `CLOUDSMITH_API_PROXY` remain supported for compatibility. In config and environment variables, the new name takes precedence over the alias. Without `proxy`, the CLI uses the `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables. When `proxy` is set, it takes precedence over them.
327
+ - `ssl_verify`: Whether or not to verify SSL certificates for HTTPS requests, including API, SAML, uploads, downloads, and MCP (default: `true`). Use `CLOUDSMITH_SSL_VERIFY=1` to enable verification or `CLOUDSMITH_SSL_VERIFY=0` / `--without-ssl-verify` to disable it. Disabling verification is dangerous; prefer disabling only strict checks where possible. The config key `api_ssl_verify`, flag `--without-api-ssl-verify` / `-S`, and environment variable `CLOUDSMITH_WITHOUT_API_SSL_VERIFY` remain supported for compatibility. Command-line settings override environment variables, which override config; within the same source, the new spelling takes precedence.
328
+ - `ssl_verify_strict`: Whether or not to apply strict X.509 certificate verification (`VERIFY_X509_STRICT`, enabled by default on Python 3.13+). Set to `false` (or use `--without-ssl-verify-strict` / `CLOUDSMITH_SSL_VERIFY_STRICT=0`) if a TLS-intercepting proxy issues certificates that fail these checks. `CLOUDSMITH_SSL_VERIFY_STRICT=1` keeps strict verification enabled (the default). Certificates are still verified.
328
329
  - `api_user_agent`: The user agent to use for requests.
329
330
 
330
331
  ### Credentials (credentials.ini)
@@ -363,29 +364,15 @@ cloudsmith auth --owner example --no-browser
363
364
 
364
365
  #### Getting Your API Key
365
366
 
366
- You can retrieve your API key using the `cloudsmith login` command:
367
+ Get your API key from the Cloudsmith web app: click your user icon in the top right corner, then click **Personal API Keys**. See [API Key](https://docs.cloudsmith.com/accounts-and-teams/api-key) for more information. If you authenticated with `cloudsmith auth`, you can also use `cloudsmith tokens create` to create an API key.
367
368
 
368
- ```
369
- cloudsmith login
370
- Login: you@example.com
371
- Password:
372
- Repeat for confirmation:
373
- ```
374
-
375
- *Note:* Please ensure you use your email for the 'Login' prompt and not your user slug/identifier.
376
-
377
- The resulting output looks something like:
378
-
379
- ```
380
- Retrieving API token for 'you@example.com' ... OK
381
- Your API token is: 1234567890abcdef1234567890abcdef
382
- ```
383
-
384
- Once you have your API key you can then put this into your `credentials.ini`, use it as an environment variable `export CLOUDSMITH_API_KEY=your_key_here` or pass it to the CLI using the `-k your_key_here` flag.
369
+ Give your API key to the CLI in one of these ways:
385
370
 
386
- For convenience the CLI will ask you if you want to install the default configuration files, complete with your API key, if they don't already exist. Say 'y' or 'yes' to create the configuration files.
371
+ - Set the `CLOUDSMITH_API_KEY` environment variable: `export CLOUDSMITH_API_KEY=your_key_here`.
372
+ - Put the key into your `credentials.ini` file.
373
+ - Pass the key to the CLI with the `-k your_key_here` flag.
387
374
 
388
- If the configuration files already exist, you'll have to manually put the API key into the configuration files, but the CLI will print out their locations.
375
+ *Note:* The `cloudsmith login` command and its `cloudsmith token` alias are deprecated. They retrieve your API key with your email address and password, and they will stop working on November 20, 2026, when Cloudsmith disables username and password login. See the [Cloudsmith changelog](https://cloudsmith.com/changelog). After that, both commands fail with a message that explains how to get an API key instead.
389
376
 
390
377
 
391
378
  ## Uploading Packages
@@ -6,6 +6,8 @@ from collections import OrderedDict
6
6
  import click.exceptions
7
7
  from click_didyoumean import DYMGroup
8
8
 
9
+ from ..core.certificate_errors import describe_certificate_error
10
+
9
11
 
10
12
  def _is_json_output_requested(exception):
11
13
  """Determine if JSON output was requested, checking context and argv."""
@@ -35,6 +37,19 @@ def _is_json_output_requested(exception):
35
37
  return False
36
38
 
37
39
 
40
+ def _is_debug_requested(args=None):
41
+ """Determine if --debug was passed (the click context is gone by now).
42
+
43
+ ``args`` are the arguments given to ``main``; click falls back to
44
+ ``sys.argv`` when they are ``None``, so we do the same.
45
+ """
46
+ import sys
47
+
48
+ if args is None:
49
+ args = sys.argv[1:]
50
+ return any(arg in ("-d", "--debug") for arg in args)
51
+
52
+
38
53
  def _format_click_exception_as_json(exception):
39
54
  """Format a ClickException as a JSON error dict."""
40
55
  return {
@@ -45,11 +60,19 @@ def _format_click_exception_as_json(exception):
45
60
  },
46
61
  "help": {
47
62
  "context": "Invalid usage",
48
- "hint": "Check your command arguments/flags.",
63
+ "hint": describe_certificate_error(exception)
64
+ or "Check your command arguments/flags.",
49
65
  },
50
66
  }
51
67
 
52
68
 
69
+ def _echo_certificate_hint(exception):
70
+ """Explain a TLS certificate failure behind ``exception`` on stderr."""
71
+ hint = describe_certificate_error(exception)
72
+ if hint:
73
+ click.echo(f"Hint: {click.style(hint, fg='yellow')}", err=True)
74
+
75
+
53
76
  class AliasGroup(DYMGroup):
54
77
  """A command group with DYM, alias and lazy-subcommand support.
55
78
 
@@ -177,4 +200,23 @@ class AliasGroup(DYMGroup):
177
200
  if not original_standalone_mode:
178
201
  raise
179
202
  e.show()
203
+ _echo_certificate_hint(e)
180
204
  sys.exit(e.exit_code)
205
+ except Exception as e: # pylint: disable=broad-exception-caught
206
+ # Anything reaching here is unexpected: click's own errors and
207
+ # handled API errors (which exit via ctx.exit) are dealt with
208
+ # above or never get this far.
209
+ if not original_standalone_mode:
210
+ raise
211
+ main_args = kwargs.get("args", args[0] if args else None)
212
+ if _is_debug_requested(main_args):
213
+ import traceback
214
+
215
+ click.echo(traceback.format_exc(), err=True, nl=False)
216
+ from ..core import telemetry
217
+
218
+ # Reporting is silent: the user sees the same line either way.
219
+ telemetry.report_exception(e)
220
+ click.echo(f"Error: {telemetry.format_exception_summary(e)}", err=True)
221
+ _echo_certificate_hint(e)
222
+ sys.exit(1)
@@ -12,7 +12,7 @@ from ...core.sso import (
12
12
  )
13
13
  from .. import decorators, utils, validators
14
14
  from ..exceptions import handle_api_exceptions
15
- from ..saml import create_configured_session, get_idp_url
15
+ from ..saml import get_idp_url
16
16
  from ..webserver import AuthenticationWebRequestHandler, AuthenticationWebServer
17
17
  from .main import main
18
18
  from .tokens import create, request_api_key
@@ -53,7 +53,7 @@ def _create_auth_server(opts, owner, session, enable_token_creation, profile):
53
53
 
54
54
 
55
55
  def _renew_existing_sso_session(opts, profile):
56
- """Return a usable existing SSO session, or fall back to browser auth."""
56
+ """Return a usable existing SAML session, or fall back to browser auth."""
57
57
  renewal = renew_sso_session(opts.api_config.host, opts.session, profile=profile)
58
58
  if renewal.status in (
59
59
  SsoRenewalStatus.RENEWED,
@@ -64,14 +64,15 @@ def _renew_existing_sso_session(opts, profile):
64
64
  renewal.error, requests.RequestException
65
65
  ):
66
66
  raise click.ClickException(
67
- "The SSO session has expired and Cloudsmith could not be reached. "
67
+ "The SAML session has expired and Cloudsmith could not be reached: "
68
+ f"{renewal.error}\n"
68
69
  "Check your connection, then run 'cloudsmith auth' again."
69
70
  ) from renewal.error
70
71
  return None
71
72
 
72
73
 
73
74
  def _report_active_sso_session(opts, renewal, use_stderr=False):
74
- """Report the usable SSO session without exposing its access token."""
75
+ """Report the usable SAML session without exposing its access token."""
75
76
  expires_at = get_access_token_expiry(renewal.access_token)
76
77
  data = {
77
78
  "authenticated": True,
@@ -84,16 +85,16 @@ def _report_active_sso_session(opts, renewal, use_stderr=False):
84
85
  return
85
86
 
86
87
  if renewal.status == SsoRenewalStatus.RENEWED:
87
- click.secho("SSO session renewed.", fg="green", err=use_stderr)
88
+ click.secho("SAML session renewed.", fg="green", err=use_stderr)
88
89
  elif renewal.error:
89
90
  click.secho(
90
- "The SSO session could not be renewed; the existing access token "
91
+ "The SAML session could not be renewed; the existing access token "
91
92
  "remains active.",
92
93
  fg="yellow",
93
94
  err=use_stderr,
94
95
  )
95
96
  else:
96
- click.secho("SSO session is active.", fg="green", err=use_stderr)
97
+ click.secho("SAML session is active.", fg="green", err=use_stderr)
97
98
  if expires_at:
98
99
  click.echo(
99
100
  f"Access token expires at {utils.fmt_datetime(expires_at)}.",
@@ -110,7 +111,7 @@ def _perform_saml_authentication(
110
111
  profile=None,
111
112
  ):
112
113
  """Perform SAML authentication via web browser and local web server."""
113
- session = create_configured_session(opts)
114
+ session = opts.session
114
115
  api_host = opts.api_config.host
115
116
 
116
117
  auth_server, port = _create_auth_server(
@@ -270,10 +271,10 @@ def authenticate(
270
271
  err=use_stderr,
271
272
  )
272
273
 
273
- # Determine if we need to refresh API after SSO (required for token operations)
274
+ # Determine if we need to refresh API after SAML (required for token operations)
274
275
  enable_token_creation = token or request_api_key_flag
275
276
 
276
- context_message = "Failed to authenticate via SSO!"
277
+ context_message = "Failed to authenticate via SAML!"
277
278
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_message):
278
279
  _perform_saml_authentication(
279
280
  opts,
@@ -9,6 +9,7 @@ Provides ``credential-helper install``, ``credential-helper uninstall``, and
9
9
  from __future__ import annotations
10
10
 
11
11
  import sys
12
+ from urllib.parse import urlsplit
12
13
 
13
14
  import click
14
15
 
@@ -78,10 +79,14 @@ def _get_installer(name: str):
78
79
  def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...]:
79
80
  """Build the terraformrc ``args`` list from the resolved config.
80
81
 
81
- Baking ``--org``/``-r``/``-P`` into the block means ``terraform init`` works
82
+ Baking ``-w``/``-r``/``-P`` into the block means ``terraform init`` works
82
83
  with no environment variables and no hand-edited config. Only values
83
- actually supplied are written, so an install without ``--org``/``--repo``/
84
- ``-P`` leaves ``args = []``.
84
+ actually supplied are written, so an install without ``-w``/``--repo``/
85
+ ``-P`` leaves ``args = []``. The API host and proxy are baked in too, so
86
+ the helper looks up domains on the same API host, through the same proxy,
87
+ as the install. A proxy URL with credentials is never baked in: Terraform
88
+ passes ``args`` on the helper's command line, where any local user can read
89
+ them.
85
90
 
86
91
  A non-default ``--config-file``/``--credentials-file`` is also baked in: the
87
92
  helper is later invoked by ``terraform init`` in a fresh process with none
@@ -91,7 +96,7 @@ def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...
91
96
  """
92
97
  args: list[str] = []
93
98
  if opts.org:
94
- args.extend(["--org", opts.org])
99
+ args.extend(["-w", opts.org])
95
100
  if repo:
96
101
  args.extend(["-r", repo])
97
102
  profile = ctx.meta.get("profile")
@@ -103,9 +108,32 @@ def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...
103
108
  creds_file = ctx.meta.get("creds_file")
104
109
  if creds_file:
105
110
  args.extend(["--credentials-file", creds_file])
111
+ if opts.api_host:
112
+ args.extend(["--api-host", opts.api_host])
113
+ if opts.proxy and not _proxy_has_credentials(opts.proxy):
114
+ args.extend(["--proxy", opts.proxy])
106
115
  return tuple(args)
107
116
 
108
117
 
118
+ def _proxy_has_credentials(proxy: str) -> bool:
119
+ """Return True if the proxy URL carries a username or password."""
120
+ parsed = urlsplit(proxy if "://" in proxy else f"//{proxy}")
121
+ return parsed.username is not None or parsed.password is not None
122
+
123
+
124
+ def _terraform_proxy_next_steps(opts) -> list[str]:
125
+ """Return the post-install guidance when the proxy was not baked in."""
126
+ if not opts.proxy or not _proxy_has_credentials(opts.proxy):
127
+ return []
128
+ return [
129
+ (
130
+ "Next steps: the proxy URL contains credentials, so it was not"
131
+ " written to the Terraform config. export CLOUDSMITH_PROXY=<proxy-url>"
132
+ " in the environment that runs `terraform init`."
133
+ ),
134
+ ]
135
+
136
+
109
137
  _REPO_FLAGS = ("-r", "--repo", "--repository")
110
138
 
111
139
 
@@ -141,6 +169,31 @@ def _terraform_next_steps(helper_args: tuple[str, ...]) -> list[str]:
141
169
  ]
142
170
 
143
171
 
172
+ def _terraform_workspace_next_steps(helper_args: tuple[str, ...]) -> list[str]:
173
+ """Return the post-install guidance when no Workspace is baked in.
174
+
175
+ The helper needs a Workspace to match custom domains and to scope the
176
+ token for a Cloudsmith-owned host.
177
+ """
178
+ if "-w" in helper_args:
179
+ return []
180
+ rc_path = _terraformrc_path()
181
+ return [
182
+ (
183
+ "Next steps: the Terraform helper needs a Workspace to match custom"
184
+ " domains and to scope tokens. Provide it in one of these ways:"
185
+ ),
186
+ (
187
+ " - export CLOUDSMITH_WORKSPACE=<your-workspace> in the environment"
188
+ " that runs `terraform init`, or"
189
+ ),
190
+ (
191
+ f" - add it to the args in {rc_path}, e.g."
192
+ ' args = ["-w", "<your-workspace>", ...].'
193
+ ),
194
+ ]
195
+
196
+
144
197
  # ---------------------------------------------------------------------------
145
198
  # install
146
199
  # ---------------------------------------------------------------------------
@@ -149,7 +202,10 @@ def _terraform_next_steps(helper_args: tuple[str, ...]) -> list[str]:
149
202
  @click.command("install")
150
203
  @click.argument("helper")
151
204
  @click.option(
152
- "--bin-dir", default=None, help="Directory to install the launcher binary."
205
+ "--bin-dir",
206
+ default=None,
207
+ help="Directory to install the launcher binary. "
208
+ "[default: ~/.cloudsmith/bin, or Terraform's plugin directory]",
153
209
  )
154
210
  @click.option(
155
211
  "--domain",
@@ -231,7 +287,7 @@ def install_cmd(
231
287
  \b
232
288
  # Terraform: bake the repository into the terraformrc args so
233
289
  # `terraform init` needs no CLOUDSMITH_REPO env var
234
- $ cloudsmith credential-helper install terraform --org acme --repo my-repo
290
+ $ cloudsmith credential-helper install terraform -w acme --repo my-repo
235
291
  """
236
292
  installer = _get_installer(helper)
237
293
 
@@ -278,7 +334,11 @@ def install_cmd(
278
334
 
279
335
  next_steps: list[str] = []
280
336
  if helper == "terraform":
281
- next_steps = _terraform_next_steps(helper_args)
337
+ next_steps = (
338
+ _terraform_workspace_next_steps(helper_args)
339
+ + _terraform_next_steps(helper_args)
340
+ + _terraform_proxy_next_steps(opts)
341
+ )
282
342
 
283
343
  data = {
284
344
  "helper": helper,
@@ -309,7 +369,10 @@ def install_cmd(
309
369
  @click.command("uninstall")
310
370
  @click.argument("helper")
311
371
  @click.option(
312
- "--bin-dir", default=None, help="Directory where the launcher binary was installed."
372
+ "--bin-dir",
373
+ default=None,
374
+ help="Directory where the launcher binary was installed. "
375
+ "[default: ~/.cloudsmith/bin, or Terraform's plugin directory]",
313
376
  )
314
377
  @click.option(
315
378
  "--dry-run",
@@ -46,8 +46,9 @@ def terraform(opts, repo, params):
46
46
 
47
47
  Provides credentials for all Cloudsmith Terraform registries:
48
48
  ``*.cloudsmith.io``, ``*.cloudsmith.com``, and any custom domains
49
- configured for the organisation (requires an organisation - ``--org``,
50
- CLOUDSMITH_ORG or ``org`` in ``config.ini`` - and a valid API key/token).
49
+ configured for the Workspace (requires a Workspace - ``-w/--workspace``,
50
+ CLOUDSMITH_WORKSPACE or ``workspace`` in ``config.ini`` - and a valid API
51
+ key/token).
51
52
 
52
53
  Accepts Terraform's calling convention — an optional verb (``get``,
53
54
  ``store``, ``forget``) followed by the hostname — so the on-PATH launcher
@@ -76,18 +77,18 @@ def terraform(opts, repo, params):
76
77
  0: Token returned, or the host is not a Cloudsmith registry
77
78
  1: Cloudsmith host with no credentials available, or an error occurred
78
79
 
79
- The token is scoped to the repository. On a standard
80
- ``*.cloudsmith.io``/``*.cloudsmith.com`` host it is ``{org}/{repo}/{token}``
81
- and the organisation is required (``--org``, ``CLOUDSMITH_ORG`` or ``org``
82
- in ``config.ini``); a standard host requested without an organisation is a
80
+ The token is scoped to the repository. On a Cloudsmith-owned host it is
81
+ ``{workspace}/{repo}/{token}`` and the Workspace is required
82
+ (``-w/--workspace``, ``CLOUDSMITH_WORKSPACE`` or ``workspace`` in
83
+ ``config.ini``); a Cloudsmith-owned host requested without a Workspace is a
83
84
  non-zero exit. On a custom domain — which is already bound to a single
84
- organisation — the org is omitted and the token is ``{repo}/{token}``. The
85
+ Workspace — the Workspace is omitted and the token is ``{repo}/{token}``. The
85
86
  repository is always required (``-r/--repo/--repository`` or
86
87
  ``CLOUDSMITH_REPO``): Terraform does not tell a credentials helper which
87
88
  repository is being requested. A non-Cloudsmith host still returns ``{}``
88
89
  and exit 0. The profile can also be supplied with ``-P/--profile``. The
89
90
  launcher forwards Terraform's ``args`` verbatim, so a terraformrc block such
90
- as ``credentials_helper "cloudsmith" { args = ["--org=acme",
91
+ as ``credentials_helper "cloudsmith" { args = ["-w", "acme",
91
92
  "--repo=my-repo", "-P", "ci"] }`` reaches this command as those options.
92
93
 
93
94
  \b
@@ -101,13 +102,13 @@ def terraform(opts, repo, params):
101
102
  # Terraform's calling convention (verb + hostname)
102
103
  $ cloudsmith credential-helper terraform --repo my-repo get terraform.cloudsmith.io
103
104
  \b
104
- # Select an org and profile explicitly (no env vars needed)
105
- $ cloudsmith credential-helper terraform --org=acme -P ci get terraform.cloudsmith.io
105
+ # Select a Workspace and profile explicitly (no env vars needed)
106
+ $ cloudsmith credential-helper terraform -w acme -P ci get terraform.cloudsmith.io
106
107
 
107
108
  \b
108
109
  Environment variables:
109
110
  CLOUDSMITH_API_KEY: API key for authentication (optional)
110
- CLOUDSMITH_ORG: Organisation slug (required to scope the token)
111
+ CLOUDSMITH_WORKSPACE: Workspace slug (required to scope the token)
111
112
  CLOUDSMITH_REPO: Repository slug the registry serves (required)
112
113
  CLOUDSMITH_PROFILE: Configuration profile to load (optional)
113
114
  """