bt-cli 0.4.61__tar.gz → 0.4.64__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 (248) hide show
  1. {bt_cli-0.4.61 → bt_cli-0.4.64}/CLAUDE.md +3 -1
  2. {bt_cli-0.4.61 → bt_cli-0.4.64}/PKG-INFO +1 -1
  3. {bt_cli-0.4.61 → bt_cli-0.4.64}/pyproject.toml +1 -1
  4. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/__init__.py +1 -1
  5. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/pws/SKILL.md +35 -0
  6. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/client/passwordsafe.py +60 -0
  7. bt_cli-0.4.64/src/bt_cli/pws/commands/sessions.py +624 -0
  8. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws/test_client.py +58 -0
  9. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws/test_commands.py +158 -1
  10. bt_cli-0.4.61/src/bt_cli/pws/commands/sessions.py +0 -243
  11. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/bt/SKILL.md +0 -0
  12. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/entitle/SKILL.md +0 -0
  13. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/epml/SKILL.md +0 -0
  14. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/epmw/SKILL.md +0 -0
  15. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/pra/SKILL.md +0 -0
  16. {bt_cli-0.4.61 → bt_cli-0.4.64}/.claude/skills/pws/SKILL.md +0 -0
  17. {bt_cli-0.4.61 → bt_cli-0.4.64}/.env.example +0 -0
  18. {bt_cli-0.4.61 → bt_cli-0.4.64}/.github/workflows/ci.yml +0 -0
  19. {bt_cli-0.4.61 → bt_cli-0.4.64}/.github/workflows/release.yml +0 -0
  20. {bt_cli-0.4.61 → bt_cli-0.4.64}/.gitignore +0 -0
  21. {bt_cli-0.4.61 → bt_cli-0.4.64}/README.md +0 -0
  22. {bt_cli-0.4.61 → bt_cli-0.4.64}/assets/cli-help.png +0 -0
  23. {bt_cli-0.4.61 → bt_cli-0.4.64}/assets/cli-output.png +0 -0
  24. {bt_cli-0.4.61 → bt_cli-0.4.64}/bt-cli.spec +0 -0
  25. {bt_cli-0.4.61 → bt_cli-0.4.64}/bt_entry.py +0 -0
  26. {bt_cli-0.4.61 → bt_cli-0.4.64}/epml-clients-server-side-filters-plan.md +0 -0
  27. {bt_cli-0.4.61 → bt_cli-0.4.64}/epml-implementation-plan.md +0 -0
  28. {bt_cli-0.4.61 → bt_cli-0.4.64}/pf-implementation-plan.md +0 -0
  29. {bt_cli-0.4.61 → bt_cli-0.4.64}/scripts/bt_entry.py +0 -0
  30. {bt_cli-0.4.61 → bt_cli-0.4.64}/scripts/pf_onboard.py +0 -0
  31. {bt_cli-0.4.61 → bt_cli-0.4.64}/scripts/sync-package-data.sh +0 -0
  32. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/cli.py +0 -0
  33. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/commands/__init__.py +0 -0
  34. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/commands/configure.py +0 -0
  35. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/commands/learn.py +0 -0
  36. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/commands/quick.py +0 -0
  37. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/__init__.py +0 -0
  38. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/auth.py +0 -0
  39. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/client.py +0 -0
  40. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/config.py +0 -0
  41. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/config_file.py +0 -0
  42. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/csv_utils.py +0 -0
  43. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/errors.py +0 -0
  44. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/output.py +0 -0
  45. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/prompts.py +0 -0
  46. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/core/rest_debug.py +0 -0
  47. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/CLAUDE.md +0 -0
  48. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/__init__.py +0 -0
  49. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
  50. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
  51. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/epml/SKILL.md +0 -0
  52. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
  53. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/pf/SKILL.md +0 -0
  54. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
  55. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/data/skills/secrets/SKILL.md +0 -0
  56. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/__init__.py +0 -0
  57. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/client/__init__.py +0 -0
  58. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/client/base.py +0 -0
  59. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/__init__.py +0 -0
  60. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/accounts.py +0 -0
  61. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/applications.py +0 -0
  62. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/auth.py +0 -0
  63. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/bundles.py +0 -0
  64. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/integrations.py +0 -0
  65. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/permissions.py +0 -0
  66. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/policies.py +0 -0
  67. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/requests.py +0 -0
  68. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/resources.py +0 -0
  69. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/roles.py +0 -0
  70. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/users.py +0 -0
  71. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/commands/workflows.py +0 -0
  72. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/__init__.py +0 -0
  73. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/bundle.py +0 -0
  74. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/common.py +0 -0
  75. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/integration.py +0 -0
  76. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/permission.py +0 -0
  77. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/policy.py +0 -0
  78. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/resource.py +0 -0
  79. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/role.py +0 -0
  80. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/user.py +0 -0
  81. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/entitle/models/workflow.py +0 -0
  82. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/__init__.py +0 -0
  83. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/client/__init__.py +0 -0
  84. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/client/base.py +0 -0
  85. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/__init__.py +0 -0
  86. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/audit.py +0 -0
  87. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/auth.py +0 -0
  88. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/client_pkg.py +0 -0
  89. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/clients.py +0 -0
  90. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/external_apis.py +0 -0
  91. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/hosts.py +0 -0
  92. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/iolog.py +0 -0
  93. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/license.py +0 -0
  94. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/quick.py +0 -0
  95. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
  96. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
  97. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
  98. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
  99. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_roles.py +0 -0
  100. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
  101. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
  102. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
  103. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
  104. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/settings.py +0 -0
  105. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/siems.py +0 -0
  106. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/commands/users.py +0 -0
  107. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epml/models/__init__.py +0 -0
  108. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/__init__.py +0 -0
  109. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/client/__init__.py +0 -0
  110. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/client/base.py +0 -0
  111. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/__init__.py +0 -0
  112. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/audits.py +0 -0
  113. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/auth.py +0 -0
  114. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/computers.py +0 -0
  115. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/events.py +0 -0
  116. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/groups.py +0 -0
  117. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/policies.py +0 -0
  118. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/quick.py +0 -0
  119. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/requests.py +0 -0
  120. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/roles.py +0 -0
  121. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/tasks.py +0 -0
  122. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/commands/users.py +0 -0
  123. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/epmw/models/__init__.py +0 -0
  124. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/__init__.py +0 -0
  125. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/client/__init__.py +0 -0
  126. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/client/base.py +0 -0
  127. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/__init__.py +0 -0
  128. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/auth.py +0 -0
  129. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/machines.py +0 -0
  130. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/tokens.py +0 -0
  131. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/user.py +0 -0
  132. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pf/commands/users.py +0 -0
  133. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/__init__.py +0 -0
  134. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/client/__init__.py +0 -0
  135. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/client/base.py +0 -0
  136. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/__init__.py +0 -0
  137. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/auth.py +0 -0
  138. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/group_policies.py +0 -0
  139. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/import_export.py +0 -0
  140. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/jump_clients.py +0 -0
  141. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/jump_groups.py +0 -0
  142. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/jump_items.py +0 -0
  143. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/jumpoints.py +0 -0
  144. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/policies.py +0 -0
  145. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/quick.py +0 -0
  146. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/teams.py +0 -0
  147. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/users.py +0 -0
  148. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/commands/vault.py +0 -0
  149. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/__init__.py +0 -0
  150. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/common.py +0 -0
  151. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/group_policy.py +0 -0
  152. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/jump_client.py +0 -0
  153. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/jump_group.py +0 -0
  154. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/jump_item.py +0 -0
  155. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/jumpoint.py +0 -0
  156. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/team.py +0 -0
  157. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/user.py +0 -0
  158. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pra/models/vault.py +0 -0
  159. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/__init__.py +0 -0
  160. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/client/__init__.py +0 -0
  161. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/client/base.py +0 -0
  162. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/client/beyondinsight.py +0 -0
  163. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/__init__.py +0 -0
  164. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/accounts.py +0 -0
  165. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/assets.py +0 -0
  166. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/attributes.py +0 -0
  167. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/audit.py +0 -0
  168. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/auth.py +0 -0
  169. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/clouds.py +0 -0
  170. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/config.py +0 -0
  171. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/credentials.py +0 -0
  172. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/databases.py +0 -0
  173. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/directories.py +0 -0
  174. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/functional.py +0 -0
  175. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/import_export.py +0 -0
  176. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/platforms.py +0 -0
  177. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/quick.py +0 -0
  178. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/search.py +0 -0
  179. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/secrets.py +0 -0
  180. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/systems.py +0 -0
  181. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/users.py +0 -0
  182. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/commands/workgroups.py +0 -0
  183. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/config.py +0 -0
  184. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/models/__init__.py +0 -0
  185. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/models/account.py +0 -0
  186. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/models/asset.py +0 -0
  187. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/models/common.py +0 -0
  188. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/pws/models/system.py +0 -0
  189. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/__init__.py +0 -0
  190. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/client/__init__.py +0 -0
  191. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/client/base.py +0 -0
  192. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/__init__.py +0 -0
  193. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/_hints.py +0 -0
  194. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/auth.py +0 -0
  195. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/dynamic.py +0 -0
  196. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/folders.py +0 -0
  197. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/integrations.py +0 -0
  198. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/leases.py +0 -0
  199. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/commands/static.py +0 -0
  200. {bt_cli-0.4.61 → bt_cli-0.4.64}/src/bt_cli/secrets/models/__init__.py +0 -0
  201. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/__init__.py +0 -0
  202. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/conftest.py +0 -0
  203. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/__init__.py +0 -0
  204. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_auth.py +0 -0
  205. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_config.py +0 -0
  206. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_config_file.py +0 -0
  207. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_errors.py +0 -0
  208. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_output.py +0 -0
  209. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/core/test_rest_debug.py +0 -0
  210. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/entitle/__init__.py +0 -0
  211. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/entitle/test_client.py +0 -0
  212. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/entitle/test_commands.py +0 -0
  213. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/entitle-smoke-test.sh +0 -0
  214. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epml/__init__.py +0 -0
  215. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epml/test_client.py +0 -0
  216. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epml/test_commands.py +0 -0
  217. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epmw/__init__.py +0 -0
  218. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epmw/test_client.py +0 -0
  219. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epmw/test_commands.py +0 -0
  220. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/epmw-quick-test-plan.md +0 -0
  221. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/fixtures/__init__.py +0 -0
  222. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/fixtures/responses.py +0 -0
  223. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/__init__.py +0 -0
  224. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/conftest.py +0 -0
  225. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/helpers.py +0 -0
  226. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_entitle_integration.py +0 -0
  227. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_epmw_integration.py +0 -0
  228. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_epmw_lifecycle.py +0 -0
  229. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_pra_integration.py +0 -0
  230. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_pra_lifecycle.py +0 -0
  231. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_pws_integration.py +0 -0
  232. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/integration/test_pws_lifecycle.py +0 -0
  233. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pf/__init__.py +0 -0
  234. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pf/test_client.py +0 -0
  235. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pf/test_commands.py +0 -0
  236. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra/__init__.py +0 -0
  237. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra/test_client.py +0 -0
  238. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra/test_commands.py +0 -0
  239. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra/test_jump_item_fixes.py +0 -0
  240. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra-smoke-test.sh +0 -0
  241. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pra-test-plan.md +0 -0
  242. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws/__init__.py +0 -0
  243. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws/test_quick_sessions.py +0 -0
  244. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws-quick-test-plan.md +0 -0
  245. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/pws-smoke-test.sh +0 -0
  246. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/secrets/__init__.py +0 -0
  247. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/secrets/test_client.py +0 -0
  248. {bt_cli-0.4.61 → bt_cli-0.4.64}/tests/secrets/test_commands.py +0 -0
@@ -1,6 +1,6 @@
1
1
  # BT-CLI
2
2
 
3
- BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, EPM Linux, and the BeyondTrust Secrets API. **Version: 0.4.61**
3
+ BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, EPM Linux, and the BeyondTrust Secrets API. **Version: 0.4.64**
4
4
 
5
5
  ## Setup
6
6
 
@@ -87,6 +87,8 @@ PASSWORD=$(bt pws quick checkout -s server -a admin --raw)
87
87
  - **PRA vault `associate -t protocol_tunnel` is MSSQL-only** (live-verified): server rejects psql/mysql/tcp/k8s with "Only SQL Server Tunnels are allowed" — use tag/criteria association for those. **TCP `--ports` needs listen;destination *pairs*** (even count; odd → 400 "number of parameters is invalid"). Jumpoint listing is `bt pra jumpoints list` (plural).
88
88
  - **PWS `/Sessions` ignores `limit`/`offset`** and returns the full session *history* every call — never `paginate()` it (infinite loop); `list_sessions` does a single GET and `bt pws sessions list` caps display client-side. `Status` codes (live-confirmed): 0=Not started, 1=Active, 2=Completed, 5=Locked, 7=Terminated; `--active`=Status 1. Active sessions have `EndTime`==`StartTime` (placeholder, not null) — identify live sessions by Status, not timestamps. **`terminate` = `POST /Sessions/{id}/Terminate`** (symmetric w/ `/Lock`); `/Sessions/{id}` is GET/PUT only (DELETE → 405).
89
89
  - **PWS SSH/RDP session establishment = `POST /Requests/{id}/Sessions`** (`{"SessionType":"SSH"|"RDP"}`), NOT `POST /Sessions` (collection is GET-only → 405). Create the request with matching `AccessType` first. **SSH** returns a ready `Command` (`ssh -p 4422 <ticket>@<proxyhost>`) + `Link`; **RDP** returns `Host`/`Port`/`Ticket` only — the `.rdp` is built client-side (`full address` = proxy `Host:Port`, `username` = `Ticket`); there's no server-side launch file (`/Sessions/RDPFile` is audit-playback → 403). Ticket is the proxy username; password is proxy-injected. `bt pws quick checkout --access-type ssh|rdp` and `bt pws quick ssh`/`quick rdp` (with `--launch`); session commands do **not** auto-checkin.
90
+ - **PWS session keystroke transcript = `GET /Sessions/{id}/Keystrokes`** → events `{KeystrokeID, TimeMarker (epoch ms), Type, Data}`. **Type 1 = user input** (typed keys; special keys as glyphs `⌫`/`→`/`↑`), **Type 2 = terminal output** (SSH stdout). SSH captures a full input+output transcript; **RDP is sparse** (typed keys / window events only, off by default → often empty). Surfaced as `bt pws sessions transcript <id>` (default = time-ordered readable transcript; `--input-only`; text/json/csv). Text trail, not the visual recording. (There is **no** `bt pws sessions export` — session *metadata* evidence is `bt pws audit export`.)
91
+ - **PWS session recording download = headless replay under `/pbsm/replay`** (there is **no** video-export API — `?video/?mp4/?webm` return JSON, not media). Flow: `GET /Sessions/{id}` for `Token`+`RecordKey`+`Protocol` → `POST /pbsm/replay` `{id:Token, record_key, protocol:"RDP"|"SSH", headless:true}` → `PUT /pbsm/replay/{rid}` `{offset:<ms>}` (seek) → `GET /pbsm/replay/{rid}?png=<scale>` (one PNG per offset) → `DELETE /pbsm/replay/{rid}`. **Warm-up:** the first `PUT` 404s (`"no such file or directory"`) until the renderer loads — retry ~0.5s. The seek response is state `{offset, next, eof, duration}`; **`next` = next recorded frame's offset**, enabling event-driven stepping. Surfaced as `bt pws sessions replay <id>` (event-driven default; `--fps`/`--interval` fixed sampling; `--from/--to`, `--scale`, `--max-frames`; `--mp4` stitches via ffmpeg, else prints the command + install hint). Always `DELETE`s the replay in `finally`.
90
92
  - Entitle permissions: Use server-side filters (`--resource`, `--user`, `--integration`) - dataset can be 20k+ records
91
93
  - Entitle users: Use `--all` flag only when needed - default fetches first page only
92
94
  - Windows builds: Rich must be pinned to `<14.0.0` (Rich 14 has PyInstaller unicode issues)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bt-cli
3
- Version: 0.4.61
3
+ Version: 0.4.64
4
4
  Summary: BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM
5
5
  Author-email: Dave Grendysz <dgrendysz@beyondtrust.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bt-cli"
7
- version = "0.4.61"
7
+ version = "0.4.64"
8
8
  description = "BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """BeyondTrust Unified Admin CLI."""
2
2
 
3
- __version__ = "0.4.61"
3
+ __version__ = "0.4.64"
@@ -195,8 +195,43 @@ bt pws sessions suspend <session_id>
195
195
  # Terminate = end permanently (cannot be resumed) - prompts unless --force
196
196
  bt pws sessions terminate <session_id>
197
197
  bt pws sessions terminate <session_id> --force
198
+
199
+ # Transcript = recorded keystrokes for a session (SSH input+output, RDP sparse)
200
+ bt pws sessions transcript <session_id> # readable transcript (default)
201
+ bt pws sessions transcript <session_id> --input-only # just the commands typed
202
+ bt pws sessions transcript <session_id> -o json | jq
203
+ bt pws sessions transcript <session_id> --file s.txt
204
+ bt pws sessions transcript <session_id> --file s.csv --format csv
205
+ ```
206
+
207
+ `transcript` pulls `GET /Sessions/{id}/Keystrokes`: events `{KeystrokeID,
208
+ TimeMarker (epoch ms), Type, Data}` where **Type 1 = user input** (typed keys,
209
+ special keys as glyphs like `⌫`/`→`) and **Type 2 = terminal output** (SSH
210
+ stdout). The default view reconstructs a time-ordered transcript (input marked
211
+ `»`, output verbatim). SSH sessions capture a full transcript; **RDP capture is
212
+ sparse** (typed keys / window events only, and only when keystroke logging is
213
+ enabled - many RDP sessions have none). This is the text trail, not the visual
214
+ recording. For session *metadata* evidence, use `bt pws audit export`.
215
+
216
+ ```bash
217
+ # Download the VISUAL recording as PNG frames (RDP screen / SSH terminal)
218
+ bt pws sessions replay <session_id> # event-driven frames + index.json
219
+ bt pws sessions replay <session_id> --mp4 # also stitch an MP4 (needs ffmpeg)
220
+ bt pws sessions replay <session_id> --fps 1 --to 120 # 1 fps for the first 2 minutes
221
+ bt pws sessions replay <session_id> --out ./review --scale 1 --max-frames 500
198
222
  ```
199
223
 
224
+ `replay` drives the headless renderer at `/pbsm/replay` (there is **no**
225
+ video-export API): create replay → seek by offset → pull one PNG per frame →
226
+ delete. By default it steps **event-driven** (following the replay state's
227
+ `next`/`eof` fields, one frame per recorded change); `--fps`/`--interval` force
228
+ fixed-rate sampling. **It's one network round-trip per frame, so long sessions
229
+ are slow** - bound them with `--fps`, `--from/--to`, or `--max-frames` (default
230
+ 3600). `--mp4` stitches with ffmpeg (H.264); if ffmpeg is missing it prints the
231
+ exact command + install instructions and leaves the frames. Works for RDP
232
+ (screen) and SSH (rendered terminal). Gotcha: the renderer needs ~0.5s warm-up
233
+ (first seek 404s), handled automatically.
234
+
200
235
  **Gotchas:**
201
236
  - `/Sessions` returns session **history**, not just active sessions, and **ignores `limit`/`offset`** (returns the full set every call - the client does a single GET, the CLI caps display client-side). Use `--active` for the live ones.
202
237
  - `Status` codes confirmed live: **0 = Not started, 1 = Active, 2 = Completed, 5 = Locked, 7 = Terminated** (3/9 are other terminal states). `--active` filters on Status == 1.
@@ -594,6 +594,66 @@ class PasswordSafeMixin:
594
594
  """
595
595
  return self.get(f"/Sessions/{session_id}")
596
596
 
597
+ def get_keystrokes(self: "PasswordSafeClient", session_id: int) -> list[dict[str, Any]]:
598
+ """Get recorded keystrokes for a session.
599
+
600
+ GET /Sessions/{id}/Keystrokes. Each event is
601
+ {KeystrokeID, SessionID, TimeMarker (epoch ms), Type, Data}. Type 1 =
602
+ user input (typed keys), Type 2 = terminal output (SSH). SSH sessions
603
+ capture a full transcript; RDP capture is sparse (often empty).
604
+
605
+ Returns:
606
+ List of keystroke events (empty list if none recorded).
607
+ """
608
+ result = self.get(f"/Sessions/{session_id}/Keystrokes")
609
+ if isinstance(result, list):
610
+ return result
611
+ if isinstance(result, dict) and "Data" in result:
612
+ return result["Data"]
613
+ return []
614
+
615
+ # --- Session replay (headless renderer under /pbsm/replay) ---
616
+ # There is no video-export endpoint: you create a replay, seek by offset,
617
+ # and pull one PNG per offset, then stitch client-side. The seek response
618
+ # carries {offset, next, eof, duration} - `next` is the next recorded
619
+ # frame's offset (ms), enabling event-driven stepping.
620
+
621
+ def create_replay(
622
+ self: "PasswordSafeClient", token: str, record_key: str, protocol: str
623
+ ) -> dict[str, Any]:
624
+ """Create a headless replay session. Returns dict with `id` (replayId)."""
625
+ return self.post(
626
+ "/pbsm/replay",
627
+ json={"id": token, "record_key": record_key, "protocol": protocol, "headless": True},
628
+ )
629
+
630
+ def seek_replay(self: "PasswordSafeClient", replay_id: str, offset_ms: int) -> dict[str, Any]:
631
+ """Seek the replay to offset (ms from start). Returns replay state.
632
+
633
+ Note: immediately after create the renderer isn't ready and this 404s
634
+ ("no such file or directory") - callers should retry with a short delay.
635
+ """
636
+ return self.put(f"/pbsm/replay/{replay_id}", json={"offset": offset_ms})
637
+
638
+ def get_replay_frame(self: "PasswordSafeClient", replay_id: str, scale: int = 1) -> bytes:
639
+ """Fetch the PNG frame at the current offset. Returns raw PNG bytes.
640
+
641
+ Uses the underlying client directly so binary content isn't coerced to
642
+ text. If the server returns non-PNG (e.g. state JSON when not ready),
643
+ the raw bytes are returned as-is for the caller to validate.
644
+ """
645
+ client = self._ensure_client()
646
+ headers = self._get_auth_headers()
647
+ response = client.request(
648
+ "GET", f"/pbsm/replay/{replay_id}", params={"png": scale}, headers=headers
649
+ )
650
+ response.raise_for_status()
651
+ return response.content
652
+
653
+ def delete_replay(self: "PasswordSafeClient", replay_id: str) -> dict[str, Any]:
654
+ """Terminate a replay session (always call this to free the renderer)."""
655
+ return self.delete(f"/pbsm/replay/{replay_id}")
656
+
597
657
  def lock_session(self: "PasswordSafeClient", session_id: int) -> dict[str, Any]:
598
658
  """Lock an active session.
599
659