humanbound-cli 0.3.1__tar.gz → 0.3.2__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 (52) hide show
  1. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/PKG-INFO +1 -1
  2. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/client.py +83 -0
  3. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/auth.py +38 -7
  4. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/main.py +3 -2
  5. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/PKG-INFO +1 -1
  6. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/pyproject.toml +1 -1
  7. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/LICENSE +0 -0
  8. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/README.md +0 -0
  9. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/__init__.py +0 -0
  10. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/__init__.py +0 -0
  11. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/api_keys.py +0 -0
  12. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/campaigns.py +0 -0
  13. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/coverage.py +0 -0
  14. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/docs.py +0 -0
  15. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/experiments.py +0 -0
  16. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/findings.py +0 -0
  17. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/guardrails.py +0 -0
  18. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/init.py +0 -0
  19. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/logs.py +0 -0
  20. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/members.py +0 -0
  21. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/orgs.py +0 -0
  22. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/posture.py +0 -0
  23. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/projects.py +0 -0
  24. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/providers.py +0 -0
  25. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/scan.py +0 -0
  26. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/test.py +0 -0
  27. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/commands/upload_logs.py +0 -0
  28. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/config.py +0 -0
  29. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/exceptions.py +0 -0
  30. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/extractors/__init__.py +0 -0
  31. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/extractors/openapi.py +0 -0
  32. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/extractors/repo.py +0 -0
  33. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/pytest_plugin/__init__.py +0 -0
  34. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/pytest_plugin/fixtures.py +0 -0
  35. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/pytest_plugin/report.py +0 -0
  36. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/report.py +0 -0
  37. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/serve/__init__.py +0 -0
  38. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/serve/config_builder.py +0 -0
  39. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/serve/local_server.py +0 -0
  40. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/serve/runtime_detector.py +0 -0
  41. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli/serve/tunnel_client.py +0 -0
  42. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/SOURCES.txt +0 -0
  43. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/dependency_links.txt +0 -0
  44. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/entry_points.txt +0 -0
  45. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/requires.txt +0 -0
  46. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/humanbound_cli.egg-info/top_level.txt +0 -0
  47. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/relay/relay.py +0 -0
  48. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/setup.cfg +0 -0
  49. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/tests/__init__.py +0 -0
  50. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/tests/cli_integration_test.py +0 -0
  51. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/tests/conftest.py +0 -0
  52. {humanbound_cli-0.3.1 → humanbound_cli-0.3.2}/tests/test_cli_commands.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: humanbound-cli
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Humanbound CLI - command line interface for AI agent security testing.
5
5
  Author-email: Kostas Siabanis <hello@humanbound.ai>, Demetris Gerogiannis <hello@humanbound.ai>
6
6
  License: Apache-2.0
@@ -206,6 +206,89 @@ ERROR_HTML = """<!DOCTYPE html>
206
206
  </html>"""
207
207
 
208
208
 
209
+ LOGOUT_HTML = """<!DOCTYPE html>
210
+ <html>
211
+ <head>
212
+ <title>Humanbound CLI - Logged Out</title>
213
+ <style>
214
+ * { margin: 0; padding: 0; box-sizing: border-box; }
215
+ body {
216
+ font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
217
+ background: linear-gradient(135deg, #0d1117 0%, #161b22 100%);
218
+ color: #e6edf3;
219
+ min-height: 100vh;
220
+ display: flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ }
224
+ .container {
225
+ text-align: center;
226
+ padding: 3rem;
227
+ background: rgba(22, 27, 34, 0.8);
228
+ border: 1px solid #30363d;
229
+ border-radius: 12px;
230
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
231
+ max-width: 480px;
232
+ }
233
+ .icon {
234
+ width: 64px;
235
+ height: 64px;
236
+ margin-bottom: 1.5rem;
237
+ background: #58a6ff;
238
+ border-radius: 50%;
239
+ display: flex;
240
+ align-items: center;
241
+ justify-content: center;
242
+ margin-left: auto;
243
+ margin-right: auto;
244
+ }
245
+ .icon svg { width: 32px; height: 32px; fill: white; }
246
+ h1 {
247
+ font-size: 1.5rem;
248
+ font-weight: 600;
249
+ margin-bottom: 0.75rem;
250
+ color: #58a6ff;
251
+ }
252
+ p {
253
+ color: #8b949e;
254
+ font-size: 0.9rem;
255
+ line-height: 1.6;
256
+ }
257
+ .command {
258
+ background: #0d1117;
259
+ border: 1px solid #30363d;
260
+ border-radius: 6px;
261
+ padding: 1rem;
262
+ margin-top: 1.5rem;
263
+ font-size: 0.85rem;
264
+ }
265
+ .command code {
266
+ color: #7ee787;
267
+ }
268
+ .prompt { color: #6e7681; }
269
+ .close-hint {
270
+ margin-top: 1.5rem;
271
+ font-size: 0.8rem;
272
+ color: #6e7681;
273
+ }
274
+ </style>
275
+ </head>
276
+ <body>
277
+ <div class="container">
278
+ <div class="icon">
279
+ <svg viewBox="0 0 24 24"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"/></svg>
280
+ </div>
281
+ <h1>Session Revoked</h1>
282
+ <p>Your local credentials and browser session have been cleared.</p>
283
+ <div class="command">
284
+ <span class="prompt">$</span> <code>hb login</code>
285
+ </div>
286
+ <p class="close-hint">You can close this tab</p>
287
+ </div>
288
+ </body>
289
+ </html>"""
290
+
291
+
209
292
  class HumanboundClient:
210
293
  """API client for Humanbound platform with OAuth authentication."""
211
294
 
@@ -65,20 +65,51 @@ def login(base_url: str, port: int, force: bool):
65
65
 
66
66
  @auth_group.command("logout")
67
67
  @click.option("--revoke", is_flag=True, help="Also clear browser SSO session (opens browser)")
68
- def logout(revoke: bool):
68
+ @click.option("--port", default=8085, help="Local callback port (default: 8085)")
69
+ def logout(revoke: bool, port: int):
69
70
  """Clear stored credentials."""
70
- import webbrowser
71
- from ..config import get_auth0_domain, get_auth0_client_id
72
-
73
71
  client = HumanboundClient()
74
72
  client.logout() # This already prints the success message
75
73
 
76
74
  if revoke:
75
+ import webbrowser
76
+ import urllib.parse
77
+ import http.server
78
+ import socketserver
79
+ from ..config import get_auth0_domain, get_auth0_client_id
80
+ from ..client import LOGOUT_HTML
81
+
77
82
  auth0_domain = get_auth0_domain()
78
83
  client_id = get_auth0_client_id()
79
- logout_url = f"https://{auth0_domain}/v2/logout?client_id={client_id}"
80
- console.print("Opening browser to clear Auth0 session...")
81
- webbrowser.open(logout_url)
84
+ return_to = f"http://localhost:{port}"
85
+
86
+ logout_url = (
87
+ f"https://{auth0_domain}/v2/logout?"
88
+ + urllib.parse.urlencode({"client_id": client_id, "returnTo": return_to})
89
+ )
90
+
91
+ class LogoutHandler(http.server.BaseHTTPRequestHandler):
92
+ def do_GET(self):
93
+ self.send_response(200)
94
+ self.send_header("Content-type", "text/html")
95
+ self.end_headers()
96
+ self.wfile.write(LOGOUT_HTML.encode())
97
+
98
+ def log_message(self, format, *args):
99
+ pass
100
+
101
+ socketserver.TCPServer.allow_reuse_address = True
102
+ server = socketserver.TCPServer(("", port), LogoutHandler)
103
+ server.timeout = 30
104
+
105
+ try:
106
+ console.print("Opening browser to clear Auth0 session...")
107
+ webbrowser.open(logout_url)
108
+ server.handle_request()
109
+ finally:
110
+ server.server_close()
111
+
112
+ console.print("[green]Browser session revoked.[/green]")
82
113
  else:
83
114
  console.print(
84
115
  "[dim]Note: Your browser may still have an active Auth0 session. "
@@ -98,10 +98,11 @@ def login_alias(ctx):
98
98
 
99
99
  @cli.command("logout")
100
100
  @click.option("--revoke", is_flag=True, help="Also clear browser SSO session (opens browser)")
101
+ @click.option("--port", default=8085, help="Local callback port (default: 8085)")
101
102
  @click.pass_context
102
- def logout_alias(ctx, revoke):
103
+ def logout_alias(ctx, revoke, port):
103
104
  """Clear stored credentials (alias for 'auth logout')."""
104
- ctx.invoke(auth.logout, revoke=revoke)
105
+ ctx.invoke(auth.logout, revoke=revoke, port=port)
105
106
 
106
107
 
107
108
  @cli.command("whoami")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: humanbound-cli
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Humanbound CLI - command line interface for AI agent security testing.
5
5
  Author-email: Kostas Siabanis <hello@humanbound.ai>, Demetris Gerogiannis <hello@humanbound.ai>
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "humanbound-cli"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  authors = [
9
9
  { name="Kostas Siabanis", email="hello@humanbound.ai" },
10
10
  { name="Demetris Gerogiannis", email="hello@humanbound.ai" },
File without changes
File without changes
File without changes