banto 5.2.3__tar.gz → 5.2.4__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 (117) hide show
  1. {banto-5.2.3 → banto-5.2.4}/PKG-INFO +4 -3
  2. {banto-5.2.3 → banto-5.2.4}/README.md +3 -2
  3. {banto-5.2.3 → banto-5.2.4}/banto/__init__.py +1 -1
  4. {banto-5.2.3 → banto-5.2.4}/banto/__main__.py +21 -1
  5. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/PKG-INFO +4 -3
  6. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/SOURCES.txt +1 -0
  7. {banto-5.2.3 → banto-5.2.4}/pyproject.toml +1 -1
  8. banto-5.2.4/tests/test_cli_version.py +58 -0
  9. {banto-5.2.3 → banto-5.2.4}/LICENSE +0 -0
  10. {banto-5.2.3 → banto-5.2.4}/banto/backend.py +0 -0
  11. {banto-5.2.3 → banto-5.2.4}/banto/broker.py +0 -0
  12. {banto-5.2.3 → banto-5.2.4}/banto/broker_cli.py +0 -0
  13. {banto-5.2.3 → banto-5.2.4}/banto/broker_client.py +0 -0
  14. {banto-5.2.3 → banto-5.2.4}/banto/broker_mcp.py +0 -0
  15. {banto-5.2.3 → banto-5.2.4}/banto/broker_setup.py +0 -0
  16. {banto-5.2.3 → banto-5.2.4}/banto/chatgpt.py +0 -0
  17. {banto-5.2.3 → banto-5.2.4}/banto/config.json +0 -0
  18. {banto-5.2.3 → banto-5.2.4}/banto/ecdsa_p256.py +0 -0
  19. {banto-5.2.3 → banto-5.2.4}/banto/guard.py +0 -0
  20. {banto-5.2.3 → banto-5.2.4}/banto/keychain.py +0 -0
  21. {banto-5.2.3 → banto-5.2.4}/banto/kimaru_evaluation.py +0 -0
  22. {banto-5.2.3 → banto-5.2.4}/banto/kimaru_material.py +0 -0
  23. {banto-5.2.3 → banto-5.2.4}/banto/lease.py +0 -0
  24. {banto-5.2.3 → banto-5.2.4}/banto/lease_cli.py +0 -0
  25. {banto-5.2.3 → banto-5.2.4}/banto/mcp_server.py +0 -0
  26. {banto-5.2.3 → banto-5.2.4}/banto/pricing.json +0 -0
  27. {banto-5.2.3 → banto-5.2.4}/banto/profiles.py +0 -0
  28. {banto-5.2.3 → banto-5.2.4}/banto/register_popup.py +0 -0
  29. {banto-5.2.3 → banto-5.2.4}/banto/rotation_capabilities.json +0 -0
  30. {banto-5.2.3 → banto-5.2.4}/banto/sealed_cli.py +0 -0
  31. {banto-5.2.3 → banto-5.2.4}/banto/sealed_signer.py +0 -0
  32. {banto-5.2.3 → banto-5.2.4}/banto/sync/__init__.py +0 -0
  33. {banto-5.2.3 → banto-5.2.4}/banto/sync/audit.py +0 -0
  34. {banto-5.2.3 → banto-5.2.4}/banto/sync/browser_batch.py +0 -0
  35. {banto-5.2.3 → banto-5.2.4}/banto/sync/browser_issuer.py +0 -0
  36. {banto-5.2.3 → banto-5.2.4}/banto/sync/browser_recorder.py +0 -0
  37. {banto-5.2.3 → banto-5.2.4}/banto/sync/capabilities.py +0 -0
  38. {banto-5.2.3 → banto-5.2.4}/banto/sync/cli.py +0 -0
  39. {banto-5.2.3 → banto-5.2.4}/banto/sync/cloudflare_token_rotator.py +0 -0
  40. {banto-5.2.3 → banto-5.2.4}/banto/sync/config.py +0 -0
  41. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/__init__.py +0 -0
  42. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/alibaba.py +0 -0
  43. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/aws_sm.py +0 -0
  44. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/aws_ssm.py +0 -0
  45. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/azure.py +0 -0
  46. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/azure_devops.py +0 -0
  47. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/base.py +0 -0
  48. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/bitbucket.py +0 -0
  49. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/circleci.py +0 -0
  50. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/cloudflare.py +0 -0
  51. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/deno.py +0 -0
  52. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/digitalocean.py +0 -0
  53. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/docker.py +0 -0
  54. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/flyio.py +0 -0
  55. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/gcp.py +0 -0
  56. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/github.py +0 -0
  57. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/gitlab.py +0 -0
  58. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/hasura.py +0 -0
  59. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/heroku.py +0 -0
  60. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/huawei.py +0 -0
  61. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/jdcloud.py +0 -0
  62. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/kubernetes.py +0 -0
  63. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/laravel_forge.py +0 -0
  64. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/local.py +0 -0
  65. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/naver.py +0 -0
  66. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/netlify.py +0 -0
  67. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/nhn.py +0 -0
  68. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/railway.py +0 -0
  69. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/render.py +0 -0
  70. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/sakura.py +0 -0
  71. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/supabase.py +0 -0
  72. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/tencent.py +0 -0
  73. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/terraform.py +0 -0
  74. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/vercel.py +0 -0
  75. {banto-5.2.3 → banto-5.2.4}/banto/sync/drivers/volcengine.py +0 -0
  76. {banto-5.2.3 → banto-5.2.4}/banto/sync/google_rotator.py +0 -0
  77. {banto-5.2.3 → banto-5.2.4}/banto/sync/history.py +0 -0
  78. {banto-5.2.3 → banto-5.2.4}/banto/sync/incident_report.py +0 -0
  79. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/__init__.py +0 -0
  80. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/base.py +0 -0
  81. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/datadog.py +0 -0
  82. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/pagerduty.py +0 -0
  83. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/slack.py +0 -0
  84. {banto-5.2.3 → banto-5.2.4}/banto/sync/notifiers/teams.py +0 -0
  85. {banto-5.2.3 → banto-5.2.4}/banto/sync/openai_rotator.py +0 -0
  86. {banto-5.2.3 → banto-5.2.4}/banto/sync/propagation.py +0 -0
  87. {banto-5.2.3 → banto-5.2.4}/banto/sync/setup.py +0 -0
  88. {banto-5.2.3 → banto-5.2.4}/banto/sync/smoke_presets.py +0 -0
  89. {banto-5.2.3 → banto-5.2.4}/banto/sync/stripe_webhook_rotator.py +0 -0
  90. {banto-5.2.3 → banto-5.2.4}/banto/sync/sync.py +0 -0
  91. {banto-5.2.3 → banto-5.2.4}/banto/sync/sync_state.py +0 -0
  92. {banto-5.2.3 → banto-5.2.4}/banto/sync/validate.py +0 -0
  93. {banto-5.2.3 → banto-5.2.4}/banto/sync/vercel_inventory.py +0 -0
  94. {banto-5.2.3 → banto-5.2.4}/banto/sync/web.py +0 -0
  95. {banto-5.2.3 → banto-5.2.4}/banto/sync/x_oauth_pkce.py +0 -0
  96. {banto-5.2.3 → banto-5.2.4}/banto/sync/x_oauth_rotator.py +0 -0
  97. {banto-5.2.3 → banto-5.2.4}/banto/sync/xai_rotator.py +0 -0
  98. {banto-5.2.3 → banto-5.2.4}/banto/vault.py +0 -0
  99. {banto-5.2.3 → banto-5.2.4}/banto/widgets.py +0 -0
  100. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/dependency_links.txt +0 -0
  101. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/entry_points.txt +0 -0
  102. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/requires.txt +0 -0
  103. {banto-5.2.3 → banto-5.2.4}/banto.egg-info/top_level.txt +0 -0
  104. {banto-5.2.3 → banto-5.2.4}/setup.cfg +0 -0
  105. {banto-5.2.3 → banto-5.2.4}/tests/test_broker.py +0 -0
  106. {banto-5.2.3 → banto-5.2.4}/tests/test_broker_setup.py +0 -0
  107. {banto-5.2.3 → banto-5.2.4}/tests/test_ecdsa_p256.py +0 -0
  108. {banto-5.2.3 → banto-5.2.4}/tests/test_hold_timeout.py +0 -0
  109. {banto-5.2.3 → banto-5.2.4}/tests/test_host_validation.py +0 -0
  110. {banto-5.2.3 → banto-5.2.4}/tests/test_keychain_account.py +0 -0
  111. {banto-5.2.3 → banto-5.2.4}/tests/test_kimaru_evaluation.py +0 -0
  112. {banto-5.2.3 → banto-5.2.4}/tests/test_kimaru_material.py +0 -0
  113. {banto-5.2.3 → banto-5.2.4}/tests/test_lease.py +0 -0
  114. {banto-5.2.3 → banto-5.2.4}/tests/test_model_profiles.py +0 -0
  115. {banto-5.2.3 → banto-5.2.4}/tests/test_recommend_profile.py +0 -0
  116. {banto-5.2.3 → banto-5.2.4}/tests/test_register_popup.py +0 -0
  117. {banto-5.2.3 → banto-5.2.4}/tests/test_sealed_signer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: banto
3
- Version: 5.2.3
3
+ Version: 5.2.4
4
4
  Summary: Local-first secret management with optional budget gating and dynamic leases
5
5
  Author: AllNew LLC
6
6
  License-Expression: LicenseRef-Dual
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  </p>
39
39
 
40
40
  <p align="center">
41
- <img src="https://img.shields.io/badge/version-5.2.3-0D3B66?style=flat-square" alt="version">
41
+ <img src="https://img.shields.io/badge/version-5.2.4-0D3B66?style=flat-square" alt="version">
42
42
  <img src="https://img.shields.io/badge/python-3.10%2B-0D3B66?style=flat-square" alt="python">
43
43
  <img src="https://img.shields.io/badge/license-Dual-262626?style=flat-square" alt="license">
44
44
  <img src="https://img.shields.io/badge/stdlib%20only-262626?style=flat-square&label=dependencies" alt="dependencies">
@@ -263,7 +263,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
263
263
  ## 💻 CLI reference
264
264
 
265
265
  <details>
266
- <summary><strong>Core commands (9)</strong></summary>
266
+ <summary><strong>Core commands (10)</strong></summary>
267
267
 
268
268
  | Command | Description |
269
269
  |---------|-------------|
@@ -276,6 +276,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
276
276
  | `banto list` | List stored keys and budget summary |
277
277
  | `banto check <model> ...` | Dry-run budget check (`--tokens`, `--n`, `--seconds`, `--quality`, `--size`) |
278
278
  | `banto init` | Copy default config to `~/.config/banto/` |
279
+ | `banto version` | Print the installed version (`banto --version` / `banto -V` also work, including in broker mode) |
279
280
 
280
281
  </details>
281
282
 
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <img src="https://img.shields.io/badge/version-5.2.3-0D3B66?style=flat-square" alt="version">
12
+ <img src="https://img.shields.io/badge/version-5.2.4-0D3B66?style=flat-square" alt="version">
13
13
  <img src="https://img.shields.io/badge/python-3.10%2B-0D3B66?style=flat-square" alt="python">
14
14
  <img src="https://img.shields.io/badge/license-Dual-262626?style=flat-square" alt="license">
15
15
  <img src="https://img.shields.io/badge/stdlib%20only-262626?style=flat-square&label=dependencies" alt="dependencies">
@@ -234,7 +234,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
234
234
  ## 💻 CLI reference
235
235
 
236
236
  <details>
237
- <summary><strong>Core commands (9)</strong></summary>
237
+ <summary><strong>Core commands (10)</strong></summary>
238
238
 
239
239
  | Command | Description |
240
240
  |---------|-------------|
@@ -247,6 +247,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
247
247
  | `banto list` | List stored keys and budget summary |
248
248
  | `banto check <model> ...` | Dry-run budget check (`--tokens`, `--n`, `--seconds`, `--quality`, `--size`) |
249
249
  | `banto init` | Copy default config to `~/.config/banto/` |
250
+ | `banto version` | Print the installed version (`banto --version` / `banto -V` also work, including in broker mode) |
250
251
 
251
252
  </details>
252
253
 
@@ -30,4 +30,4 @@ __all__ = [
30
30
  "KeyNotFoundError",
31
31
  "ProfileManager",
32
32
  ]
33
- __version__ = "5.2.3"
33
+ __version__ = "5.2.4"
@@ -11,6 +11,7 @@ Commands:
11
11
  list List stored provider keys
12
12
  check <model> ... Dry-run budget check for a model
13
13
  init Copy default config to ~/.config/banto/
14
+ version Show the installed version (also --version, -V)
14
15
  """
15
16
 
16
17
  import getpass
@@ -475,6 +476,15 @@ def cmd_sealed(args: list[str]) -> None:
475
476
  cmd_sealed_dispatch(args)
476
477
 
477
478
 
479
+ def _print_version() -> None:
480
+ from . import __version__
481
+ print(f"banto {__version__}")
482
+
483
+
484
+ def cmd_version(args: list[str]) -> None:
485
+ _print_version()
486
+
487
+
478
488
  def cmd_chatgpt(args: list[str]) -> None:
479
489
  if not args or args[0] in ("-h", "--help"):
480
490
  print("banto chatgpt: Connect banto to ChatGPT\n")
@@ -503,10 +513,18 @@ COMMANDS = {
503
513
  "lease": cmd_lease,
504
514
  "sealed": cmd_sealed,
505
515
  "chatgpt": cmd_chatgpt,
516
+ "version": cmd_version,
506
517
  }
507
518
 
519
+ VERSION_FLAGS = ("--version", "-V", "version")
520
+
508
521
 
509
522
  def main() -> None:
523
+ # Handled before broker routing so it works in broker mode too and never
524
+ # touches Keychain, the broker socket, or config files.
525
+ if len(sys.argv) > 1 and sys.argv[1] in VERSION_FLAGS:
526
+ _print_version()
527
+ return
510
528
  if len(sys.argv) > 1 and sys.argv[1] == "broker":
511
529
  from .broker import main as broker_main
512
530
  sys.argv.pop(1)
@@ -518,7 +536,8 @@ def main() -> None:
518
536
  return
519
537
  if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
520
538
  print("banto: Budget-gated API key vault for LLM applications\n")
521
- print("Usage: banto <command> [args]\n")
539
+ print("Usage: banto <command> [args]")
540
+ print(" banto --version | -V\n")
522
541
  print("Commands:")
523
542
  print(" broker <cmd> Common Keychain process: install, health, enable, call")
524
543
  print(" status Show budget status (with per-provider/model breakdown)")
@@ -534,6 +553,7 @@ def main() -> None:
534
553
  print(" lease <cmd> Dynamic secrets with TTL and auto-revoke")
535
554
  print(" sealed <cmd> Secure Enclave sealed signing (non-extractable keys)")
536
555
  print(" chatgpt connect Connect banto to ChatGPT (starts tunnel)")
556
+ print(" version Show the installed version (also --version, -V)")
537
557
  print()
538
558
  print("Budget examples:")
539
559
  print(" banto budget Show all limits")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: banto
3
- Version: 5.2.3
3
+ Version: 5.2.4
4
4
  Summary: Local-first secret management with optional budget gating and dynamic leases
5
5
  Author: AllNew LLC
6
6
  License-Expression: LicenseRef-Dual
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  </p>
39
39
 
40
40
  <p align="center">
41
- <img src="https://img.shields.io/badge/version-5.2.3-0D3B66?style=flat-square" alt="version">
41
+ <img src="https://img.shields.io/badge/version-5.2.4-0D3B66?style=flat-square" alt="version">
42
42
  <img src="https://img.shields.io/badge/python-3.10%2B-0D3B66?style=flat-square" alt="python">
43
43
  <img src="https://img.shields.io/badge/license-Dual-262626?style=flat-square" alt="license">
44
44
  <img src="https://img.shields.io/badge/stdlib%20only-262626?style=flat-square&label=dependencies" alt="dependencies">
@@ -263,7 +263,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
263
263
  ## 💻 CLI reference
264
264
 
265
265
  <details>
266
- <summary><strong>Core commands (9)</strong></summary>
266
+ <summary><strong>Core commands (10)</strong></summary>
267
267
 
268
268
  | Command | Description |
269
269
  |---------|-------------|
@@ -276,6 +276,7 @@ banto budget --provider openai 30 # $30/month for OpenAI
276
276
  | `banto list` | List stored keys and budget summary |
277
277
  | `banto check <model> ...` | Dry-run budget check (`--tokens`, `--n`, `--seconds`, `--quality`, `--size`) |
278
278
  | `banto init` | Copy default config to `~/.config/banto/` |
279
+ | `banto version` | Print the installed version (`banto --version` / `banto -V` also work, including in broker mode) |
279
280
 
280
281
  </details>
281
282
 
@@ -101,6 +101,7 @@ banto/sync/notifiers/slack.py
101
101
  banto/sync/notifiers/teams.py
102
102
  tests/test_broker.py
103
103
  tests/test_broker_setup.py
104
+ tests/test_cli_version.py
104
105
  tests/test_ecdsa_p256.py
105
106
  tests/test_hold_timeout.py
106
107
  tests/test_host_validation.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "banto"
7
- version = "5.2.3"
7
+ version = "5.2.4"
8
8
  description = "Local-first secret management with optional budget gating and dynamic leases"
9
9
  readme = "README.md"
10
10
  license = "LicenseRef-Dual"
@@ -0,0 +1,58 @@
1
+ # Copyright 2025-2026 AllNew LLC
2
+ # Licensed under LicenseRef-Dual (see LICENSE)
3
+ """Tests for `banto --version` / `-V` / `version`."""
4
+
5
+ import subprocess
6
+ import sys
7
+ from unittest.mock import Mock
8
+
9
+ import pytest
10
+
11
+ import banto
12
+ from banto import __main__ as cli
13
+ from banto import broker_cli
14
+ from banto.broker_client import BrokerClient
15
+
16
+ FLAGS = ["--version", "-V", "version"]
17
+
18
+
19
+ @pytest.mark.parametrize("flag", FLAGS)
20
+ def test_version_prints_and_exits_zero(flag, monkeypatch, capsys):
21
+ monkeypatch.setattr(sys, "argv", ["banto", flag])
22
+ cli.main() # returns normally (exit status 0)
23
+ assert capsys.readouterr().out == f"banto {banto.__version__}\n"
24
+
25
+
26
+ @pytest.mark.parametrize("flag", FLAGS)
27
+ def test_version_works_in_broker_mode(flag, tmp_path, monkeypatch, capsys):
28
+ (tmp_path / "required").touch()
29
+ monkeypatch.setattr(broker_cli, "runtime_dir", lambda: tmp_path)
30
+ call = Mock(side_effect=AssertionError("broker must not be called"))
31
+ monkeypatch.setattr(BrokerClient, "call", call)
32
+ monkeypatch.setattr(sys, "argv", ["banto", flag])
33
+ cli.main()
34
+ assert capsys.readouterr().out == f"banto {banto.__version__}\n"
35
+ call.assert_not_called()
36
+
37
+
38
+ @pytest.mark.parametrize("flag", ["--version", "-V"])
39
+ def test_version_subprocess_exit_code(flag):
40
+ proc = subprocess.run(
41
+ [sys.executable, "-m", "banto", flag], capture_output=True, text=True, timeout=60
42
+ )
43
+ assert proc.returncode == 0
44
+ assert proc.stdout.strip() == f"banto {banto.__version__}"
45
+
46
+
47
+ def test_help_lists_version(monkeypatch, capsys):
48
+ monkeypatch.setattr(sys, "argv", ["banto", "--help"])
49
+ with pytest.raises(SystemExit) as exc:
50
+ cli.main()
51
+ assert exc.value.code == 0
52
+ out = capsys.readouterr().out
53
+ assert "--version" in out
54
+ assert "version " in out
55
+
56
+
57
+ def test_version_is_registered_command():
58
+ assert "version" in cli.COMMANDS
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes