plugin-scanner 2.0.74__tar.gz → 2.0.75__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 (331) hide show
  1. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/commands.py +77 -4
  5. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/render.py +9 -0
  6. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/runtime/surface_server.py +7 -2
  7. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/version.py +1 -1
  8. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_cli.py +94 -0
  9. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_surface_server.py +43 -0
  10. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.clusterfuzzlite/Dockerfile +0 -0
  11. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.clusterfuzzlite/build.sh +0 -0
  12. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.clusterfuzzlite/project.yaml +0 -0
  13. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  14. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.dockerignore +0 -0
  15. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/CODEOWNERS +0 -0
  16. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  17. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  19. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/dependabot.yml +0 -0
  20. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/ci.yml +0 -0
  21. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/codeql.yml +0 -0
  22. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/dependabot-uv-lock.yml +0 -0
  23. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/fuzz.yml +0 -0
  24. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/harness-smoke.yml +0 -0
  25. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/publish.yml +0 -0
  26. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.github/workflows/scorecard.yml +0 -0
  27. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.gitignore +0 -0
  28. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/.pre-commit-hooks.yaml +0 -0
  29. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/CONTRIBUTING.md +0 -0
  30. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/Dockerfile +0 -0
  31. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/LICENSE +0 -0
  32. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/README.md +0 -0
  33. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/SECURITY.md +0 -0
  34. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/index.html +0 -0
  35. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/package.json +0 -0
  36. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/pnpm-lock.yaml +0 -0
  37. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/apple-touch-icon.png +0 -0
  38. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  39. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/brand/Logo_Whole.png +0 -0
  40. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/favicon-16x16.png +0 -0
  41. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/favicon-32x32.png +0 -0
  42. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/public/favicon.ico +0 -0
  43. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/app.tsx +0 -0
  44. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/approval-center-layout.tsx +0 -0
  45. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/approval-center-primitives.tsx +0 -0
  46. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/approval-center-utils.ts +0 -0
  47. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/fleet-workspace.tsx +0 -0
  48. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/guard-api.ts +0 -0
  49. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/guard-demo.ts +0 -0
  50. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/guard-types.ts +0 -0
  51. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/main.tsx +0 -0
  52. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/receipts-workspace.tsx +0 -0
  53. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/runtime-overview.tsx +0 -0
  54. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/settings-workspace.tsx +0 -0
  55. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/styles.css +0 -0
  56. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/src/vite-env.d.ts +0 -0
  57. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/tsconfig.json +0 -0
  58. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/dashboard/vite.config.ts +0 -0
  59. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docker-requirements.txt +0 -0
  60. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/approval-audit.md +0 -0
  61. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/architecture.md +0 -0
  62. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/get-started.md +0 -0
  63. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/harness-support.md +0 -0
  64. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/local-vs-cloud.md +0 -0
  65. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/guard/testing-matrix.md +0 -0
  66. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/trust/mcp-trust-draft.md +0 -0
  67. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/trust/plugin-trust-draft.md +0 -0
  68. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/docs/trust/skill-trust-local.md +0 -0
  69. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/fuzzers/manifest_fuzzer.py +0 -0
  70. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/requirements.txt +0 -0
  71. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/schemas/plugin-quality.v1.json +0 -0
  72. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/schemas/scan-result.v1.json +0 -0
  73. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/schemas/verify-result.v1.json +0 -0
  74. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/__init__.py +0 -0
  75. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/action_runner.py +0 -0
  76. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  77. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  78. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  79. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/claude.py +0 -0
  80. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  81. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  82. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  83. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  84. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  85. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  86. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  87. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  88. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  89. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/security.py +0 -0
  90. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  91. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/cli.py +0 -0
  92. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/cli_ui.py +0 -0
  93. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/config.py +0 -0
  94. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  95. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  96. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  97. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  98. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  99. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  100. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  101. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  102. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  103. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/github_reporting.py +0 -0
  104. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  105. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  106. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  107. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  108. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  109. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  110. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  111. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  112. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  113. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  114. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  115. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  116. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  117. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  118. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  119. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  120. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  121. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  122. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  123. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  124. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  125. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  126. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  127. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  128. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  129. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/config.py +0 -0
  130. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  131. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  132. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  133. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  134. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  135. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  136. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  137. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  138. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  139. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  140. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  141. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  142. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  143. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  144. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  145. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  146. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/incident.py +0 -0
  147. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  148. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  149. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/models.py +0 -0
  150. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  151. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  152. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/protect.py +0 -0
  153. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  154. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  155. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  156. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  157. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  158. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  159. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/risk.py +0 -0
  160. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  161. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  162. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  163. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  164. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  165. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  166. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  167. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/shims.py +0 -0
  168. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/store.py +0 -0
  169. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  170. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  171. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/guard/types.py +0 -0
  172. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  173. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  174. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  175. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  176. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  177. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/models.py +0 -0
  178. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/path_support.py +0 -0
  179. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/policy.py +0 -0
  180. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  181. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/repo_detect.py +0 -0
  182. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/reporting.py +0 -0
  183. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  184. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/rules/registry.py +0 -0
  185. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/rules/specs.py +0 -0
  186. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/scanner.py +0 -0
  187. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/submission.py +0 -0
  188. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/suppressions.py +0 -0
  189. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  190. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  191. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  192. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_models.py +0 -0
  193. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  194. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  195. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  196. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/trust_specs.py +0 -0
  197. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/src/codex_plugin_scanner/verification.py +0 -0
  198. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/__init__.py +0 -0
  199. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/conftest.py +0 -0
  200. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/__init__.py +0 -0
  201. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  202. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  203. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/bad-plugin/secrets.js +0 -0
  204. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  205. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  206. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/README.md +0 -0
  207. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  208. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  209. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  210. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/code-quality-bad/evil.js +0 -0
  211. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/code-quality-bad/inject.js +0 -0
  212. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  213. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  214. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/README.md +0 -0
  215. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  216. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  217. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  218. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  219. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/.codexignore +0 -0
  220. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/LICENSE +0 -0
  221. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/README.md +0 -0
  222. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  223. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  224. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  225. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  226. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  227. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  228. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  229. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  230. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  231. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  232. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  233. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  234. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  235. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  236. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  237. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  238. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  239. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  240. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  241. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  242. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/mcp-canary-server.py +0 -0
  243. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  244. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  245. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/mit-license/LICENSE +0 -0
  246. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  247. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  248. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  249. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  250. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  251. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  252. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  253. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  254. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  255. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  256. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  257. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  258. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  259. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  260. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  261. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  262. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  263. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  264. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/LICENSE +0 -0
  265. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/README.md +0 -0
  266. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  267. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  268. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  269. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  270. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  271. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  272. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  273. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  274. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test-trust-scoring.py +0 -0
  275. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test-trust-specs.py +0 -0
  276. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_action_runner.py +0 -0
  277. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_best_practices.py +0 -0
  278. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_cisco_install_surfaces.py +0 -0
  279. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_cli.py +0 -0
  280. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_code_quality.py +0 -0
  281. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_config.py +0 -0
  282. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_coverage_remaining.py +0 -0
  283. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_ecosystems.py +0 -0
  284. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_edge_cases.py +0 -0
  285. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_final_coverage.py +0 -0
  286. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_approvals.py +0 -0
  287. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_bootstrap.py +0 -0
  288. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_capabilities.py +0 -0
  289. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_claude_adapter.py +0 -0
  290. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_codex_e2e.py +0 -0
  291. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_codex_install.py +0 -0
  292. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_codex_proxy.py +0 -0
  293. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_config_paths.py +0 -0
  294. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_connect_flow.py +0 -0
  295. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_consumer_mode.py +0 -0
  296. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_copilot_adapter.py +0 -0
  297. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_copilot_proxy.py +0 -0
  298. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_daemon_manager.py +0 -0
  299. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_event_schema_v1.py +0 -0
  300. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_events.py +0 -0
  301. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_launch_env.py +0 -0
  302. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_opencode_proxy.py +0 -0
  303. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_product_flow.py +0 -0
  304. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_protect.py +0 -0
  305. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_render.py +0 -0
  306. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_risk.py +0 -0
  307. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_runtime.py +0 -0
  308. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_store_migrations.py +0 -0
  309. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_guard_verdicts.py +0 -0
  310. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_hermes_adapter.py +0 -0
  311. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_integration.py +0 -0
  312. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_lint_fixes.py +0 -0
  313. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_live_cisco_smoke.py +0 -0
  314. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_manifest.py +0 -0
  315. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_marketplace.py +0 -0
  316. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_mcp_security.py +0 -0
  317. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_operational_security.py +0 -0
  318. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_policy.py +0 -0
  319. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_quality_artifact.py +0 -0
  320. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_rule_registry.py +0 -0
  321. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_scanner.py +0 -0
  322. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_schema_contracts.py +0 -0
  323. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_security.py +0 -0
  324. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_security_ops.py +0 -0
  325. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_skill_security.py +0 -0
  326. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_submission.py +0 -0
  327. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_trust_scoring.py +0 -0
  328. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_trust_specs.py +0 -0
  329. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_verification.py +0 -0
  330. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/tests/test_versioning.py +0 -0
  331. {plugin_scanner-2.0.74 → plugin_scanner-2.0.75}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.74
3
+ Version: 2.0.75
4
4
  Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
5
5
  Project-URL: Homepage, https://github.com/hashgraph-online/ai-plugin-scanner
6
6
  Project-URL: Repository, https://github.com/hashgraph-online/ai-plugin-scanner
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.74"
7
+ version = "2.0.75"
8
8
  description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hol-guard"
7
- version = "2.0.74"
7
+ version = "2.0.75"
8
8
  description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -112,6 +112,7 @@ _GUARD_HELP_GROUPS = (
112
112
  "Everyday protection:\n"
113
113
  " start First-run setup and the Guard operating loop\n"
114
114
  " status Current local protection state and next actions\n"
115
+ " dashboard Open the local Guard dashboard in your browser\n"
115
116
  " run Enforce Guard before a harness launch\n"
116
117
  " approvals Resolve the current request queue\n"
117
118
  " receipts Review recent local decisions\n"
@@ -204,7 +205,7 @@ def _configure_guard_parser(guard_parser: argparse.ArgumentParser) -> None:
204
205
  required=True,
205
206
  parser_class=FriendlyArgumentParser,
206
207
  metavar=(
207
- "{start,status,bootstrap,detect,install,update,uninstall,run,protect,preflight,scan,diff,receipts,inventory,abom,"
208
+ "{start,status,dashboard,bootstrap,detect,install,update,uninstall,run,protect,preflight,scan,diff,receipts,inventory,abom,"
208
209
  "approvals,explain,allow,deny,policies,exceptions,advisories,events,doctor,connect,login,sync,device,bridge}"
209
210
  ),
210
211
  )
@@ -217,6 +218,17 @@ def _configure_guard_parser(guard_parser: argparse.ArgumentParser) -> None:
217
218
  _add_guard_common_args(status_parser)
218
219
  status_parser.add_argument("--json", action="store_true")
219
220
 
221
+ dashboard_parser = guard_subparsers.add_parser(
222
+ "dashboard",
223
+ help="Open the local Guard dashboard in your browser",
224
+ )
225
+ _add_guard_common_args(dashboard_parser)
226
+ dashboard_parser.add_argument("--json", action="store_true")
227
+
228
+ admin_parser = guard_subparsers.add_parser("admin", help=argparse.SUPPRESS)
229
+ _add_guard_common_args(admin_parser)
230
+ admin_parser.add_argument("--json", action="store_true")
231
+
220
232
  bootstrap_parser = guard_subparsers.add_parser(
221
233
  "bootstrap",
222
234
  help="Detect a harness, start the approval center, and install Guard for the best local target",
@@ -513,6 +525,7 @@ def _configure_guard_parser(guard_parser: argparse.ArgumentParser) -> None:
513
525
  hermes_mcp_proxy_parser.add_argument("--server", required=True)
514
526
  hermes_mcp_proxy_parser.add_argument("--stdio", action="store_true")
515
527
  hidden_commands = {
528
+ "admin",
516
529
  "hook",
517
530
  "daemon",
518
531
  "codex-mcp-proxy",
@@ -660,6 +673,43 @@ def run_guard_command(
660
673
  _emit("status", payload, getattr(args, "json", False))
661
674
  return 0
662
675
 
676
+ if args.guard_command in {"dashboard", "admin"}:
677
+ try:
678
+ approval_center_url = ensure_guard_daemon(guard_home)
679
+ except RuntimeError as error:
680
+ if getattr(args, "json", False):
681
+ _emit(
682
+ "dashboard",
683
+ {
684
+ "generated_at": _now(),
685
+ "opened": False,
686
+ "error": str(error),
687
+ },
688
+ True,
689
+ )
690
+ else:
691
+ print(str(error), file=sys.stderr)
692
+ return 1
693
+ open_result = _open_approval_center(
694
+ approval_center_url,
695
+ store=store,
696
+ config=config,
697
+ open_key="dashboard",
698
+ force_open=True,
699
+ )
700
+ _emit(
701
+ "dashboard",
702
+ {
703
+ "generated_at": _now(),
704
+ "approval_center_url": approval_center_url,
705
+ "browser_url": open_result.get("browser_url"),
706
+ "opened": bool(open_result.get("opened")),
707
+ "reason": str(open_result.get("reason") or "unknown"),
708
+ },
709
+ getattr(args, "json", False),
710
+ )
711
+ return 0
712
+
663
713
  if args.guard_command == "bootstrap":
664
714
  try:
665
715
  payload = build_guard_bootstrap_payload(
@@ -3278,17 +3328,28 @@ def _headless_approval_resolver(
3278
3328
  return resolve
3279
3329
 
3280
3330
 
3281
- def _open_approval_center(approval_center_url: str, *, store: GuardStore, config, open_key: str | None = None) -> None:
3331
+ def _open_approval_center(
3332
+ approval_center_url: str,
3333
+ *,
3334
+ store: GuardStore,
3335
+ config: GuardConfig,
3336
+ open_key: str | None = None,
3337
+ force_open: bool = False,
3338
+ ) -> dict[str, object]:
3282
3339
  surface_runtime = GuardSurfaceRuntime(store)
3283
3340
  auth_token = load_guard_daemon_auth_token(store.guard_home)
3284
- surface_runtime.ensure_surface(
3341
+ browser_url = _approval_center_browser_url(approval_center_url, auth_token)
3342
+ open_result = surface_runtime.ensure_surface(
3285
3343
  surface="approval-center",
3286
3344
  approval_center_url=approval_center_url,
3287
- browser_url=_approval_center_browser_url(approval_center_url, auth_token),
3345
+ browser_url=browser_url,
3288
3346
  approval_surface_policy=config.approval_surface_policy,
3289
3347
  open_key=open_key or approval_center_url,
3348
+ force_open=force_open,
3290
3349
  opener=webbrowser.open,
3291
3350
  )
3351
+ open_result["browser_url"] = _public_approval_center_url(browser_url) or approval_center_url
3352
+ return open_result
3292
3353
 
3293
3354
 
3294
3355
  def _approval_center_browser_url(approval_center_url: str, auth_token: str | None) -> str | None:
@@ -3304,6 +3365,18 @@ def _approval_center_browser_url(approval_center_url: str, auth_token: str | Non
3304
3365
  return urllib.parse.urlunparse(parsed._replace(fragment=urllib.parse.urlencode(fragment_pairs)))
3305
3366
 
3306
3367
 
3368
+ def _public_approval_center_url(browser_url: str | None) -> str | None:
3369
+ if browser_url is None:
3370
+ return None
3371
+ parsed = urllib.parse.urlparse(browser_url)
3372
+ fragment_pairs = [
3373
+ (key, value)
3374
+ for key, value in urllib.parse.parse_qsl(parsed.fragment, keep_blank_values=True)
3375
+ if key != "guard-token"
3376
+ ]
3377
+ return urllib.parse.urlunparse(parsed._replace(fragment=urllib.parse.urlencode(fragment_pairs)))
3378
+
3379
+
3307
3380
  def _approval_surface_policy_for_flow(config_policy: str, approval_flow: dict[str, object]) -> str:
3308
3381
  if approval_flow.get("tier") != "approval-center":
3309
3382
  return "notify-only"
@@ -654,6 +654,14 @@ def _render_connect(console: Console, payload: dict[str, object]) -> None:
654
654
  console.print(_build_steps_panel(_coerce_dict_list(payload.get("next_steps"))))
655
655
 
656
656
 
657
+ def _render_dashboard(console: Console, payload: dict[str, object]) -> None:
658
+ body = Table.grid(padding=(0, 1))
659
+ body.add_row("Dashboard", str(payload.get("approval_center_url") or "unknown"))
660
+ if payload.get("opened") is not None:
661
+ body.add_row("Browser opened", _bool_label(bool(payload.get("opened"))))
662
+ console.print(Panel(body, title="HOL Guard dashboard", border_style="cyan"))
663
+
664
+
657
665
  def _render_sync(console: Console, payload: dict[str, object]) -> None:
658
666
  body = Table.grid(padding=(0, 1))
659
667
  body.add_row("Synced at", str(payload.get("synced_at") or "unknown"))
@@ -1615,6 +1623,7 @@ _RENDERERS: dict[str, Any] = {
1615
1623
  "approvals": _render_approvals,
1616
1624
  "start": _render_start,
1617
1625
  "status": _render_status,
1626
+ "dashboard": _render_dashboard,
1618
1627
  "connect": _render_connect,
1619
1628
  "bootstrap": _render_bootstrap,
1620
1629
  "detect": _render_detect,
@@ -332,10 +332,15 @@ class GuardSurfaceRuntime:
332
332
  approval_surface_policy: str,
333
333
  open_key: str,
334
334
  opener: Callable[[str], object],
335
+ force_open: bool = False,
335
336
  ) -> dict[str, object]:
336
- if approval_surface_policy in {"notify-only", "never-auto-open"}:
337
+ if approval_surface_policy in {"notify-only", "never-auto-open"} and not force_open:
337
338
  return {"surface": surface, "opened": False, "reason": "policy-disabled", "open_key": open_key}
338
- if approval_surface_policy == "auto-open-once" and self.has_surface_opened(surface, open_key):
339
+ if (
340
+ approval_surface_policy == "auto-open-once"
341
+ and not force_open
342
+ and self.has_surface_opened(surface, open_key)
343
+ ):
339
344
  return {"surface": surface, "opened": False, "reason": "already-opened", "open_key": open_key}
340
345
  if self.has_live_surface(surface):
341
346
  return {"surface": surface, "opened": False, "reason": "live-client", "open_key": open_key}
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for tool version."""
2
2
 
3
- __version__ = "2.0.74"
3
+ __version__ = "2.0.75"
@@ -6048,6 +6048,100 @@ url = http://127.0.0.1:8787/guard-canary
6048
6048
  assert connect_output["reason"] == "Guard sync requires a Pro or Team plan."
6049
6049
  assert connect_output["sync_message"] == "Guard sync requires a Pro or Team plan."
6050
6050
 
6051
+ def test_guard_dashboard_opens_local_approval_center(self, tmp_path, capsys, monkeypatch):
6052
+ home_dir = tmp_path / "home"
6053
+ opened_urls: list[str] = []
6054
+ open_keys: list[str | None] = []
6055
+ force_open_flags: list[bool] = []
6056
+
6057
+ monkeypatch.setattr(
6058
+ guard_commands_module,
6059
+ "ensure_guard_daemon",
6060
+ lambda guard_home: "http://127.0.0.1:5474",
6061
+ )
6062
+ monkeypatch.setattr(
6063
+ guard_commands_module,
6064
+ "_open_approval_center",
6065
+ lambda approval_center_url, *, store, config, open_key=None, force_open=False: (
6066
+ opened_urls.append(approval_center_url),
6067
+ open_keys.append(open_key),
6068
+ force_open_flags.append(force_open),
6069
+ {"opened": True, "reason": "opened", "browser_url": approval_center_url},
6070
+ )[-1],
6071
+ )
6072
+
6073
+ rc = main(["guard", "dashboard", "--home", str(home_dir), "--json"])
6074
+ output = json.loads(capsys.readouterr().out)
6075
+
6076
+ assert rc == 0
6077
+ assert opened_urls == ["http://127.0.0.1:5474"]
6078
+ assert open_keys == ["dashboard"]
6079
+ assert force_open_flags == [True]
6080
+ assert output["approval_center_url"] == "http://127.0.0.1:5474"
6081
+ assert output["browser_url"] == "http://127.0.0.1:5474"
6082
+ assert output["opened"] is True
6083
+ assert output["reason"] == "opened"
6084
+
6085
+ def test_guard_admin_alias_opens_local_approval_center(self, tmp_path, capsys, monkeypatch):
6086
+ home_dir = tmp_path / "home"
6087
+ opened_urls: list[str] = []
6088
+ open_keys: list[str | None] = []
6089
+ force_open_flags: list[bool] = []
6090
+
6091
+ monkeypatch.setattr(
6092
+ guard_commands_module,
6093
+ "ensure_guard_daemon",
6094
+ lambda guard_home: "http://127.0.0.1:5474",
6095
+ )
6096
+ monkeypatch.setattr(
6097
+ guard_commands_module,
6098
+ "_open_approval_center",
6099
+ lambda approval_center_url, *, store, config, open_key=None, force_open=False: (
6100
+ opened_urls.append(approval_center_url),
6101
+ open_keys.append(open_key),
6102
+ force_open_flags.append(force_open),
6103
+ {"opened": False, "reason": "policy-disabled", "browser_url": approval_center_url},
6104
+ )[-1],
6105
+ )
6106
+
6107
+ rc = main(["guard", "admin", "--home", str(home_dir), "--json"])
6108
+ output = json.loads(capsys.readouterr().out)
6109
+
6110
+ assert rc == 0
6111
+ assert opened_urls == ["http://127.0.0.1:5474"]
6112
+ assert open_keys == ["dashboard"]
6113
+ assert force_open_flags == [True]
6114
+ assert output["approval_center_url"] == "http://127.0.0.1:5474"
6115
+ assert output["browser_url"] == "http://127.0.0.1:5474"
6116
+ assert output["opened"] is False
6117
+ assert output["reason"] == "policy-disabled"
6118
+
6119
+ def test_guard_dashboard_returns_error_when_daemon_start_fails(self, tmp_path, capsys, monkeypatch):
6120
+ home_dir = tmp_path / "home"
6121
+
6122
+ monkeypatch.setattr(
6123
+ guard_commands_module,
6124
+ "ensure_guard_daemon",
6125
+ lambda guard_home: (_ for _ in ()).throw(RuntimeError("dashboard_unavailable")),
6126
+ )
6127
+
6128
+ rc = main(["guard", "dashboard", "--home", str(home_dir), "--json"])
6129
+ output = json.loads(capsys.readouterr().out)
6130
+
6131
+ assert rc == 1
6132
+ assert output["opened"] is False
6133
+ assert output["error"] == "dashboard_unavailable"
6134
+
6135
+ def test_public_approval_center_url_strips_guard_token(self):
6136
+ browser_url = guard_commands_module._approval_center_browser_url(
6137
+ "http://127.0.0.1:5474#section=inbox",
6138
+ "secret-token",
6139
+ )
6140
+
6141
+ assert browser_url is not None
6142
+ assert "guard-token=secret-token" in browser_url
6143
+ assert "guard-token=" not in guard_commands_module._public_approval_center_url(browser_url)
6144
+
6051
6145
  def test_guard_connect_pending_output_uses_product_copy_for_sign_in_gap(self, capsys):
6052
6146
  emit_guard_payload(
6053
6147
  "connect",
@@ -1620,3 +1620,46 @@ class TestGuardSurfaceServer:
1620
1620
  assert operation["operation_type"] == "run"
1621
1621
  assert approval["request_ids"] == ["req-1", "req-2"]
1622
1622
  assert resumed["status"] == "completed"
1623
+
1624
+ def test_guard_surface_runtime_force_open_bypasses_auto_open_once(self, tmp_path) -> None:
1625
+ store = GuardStore(tmp_path / "guard-home")
1626
+ runtime = GuardSurfaceRuntime(store)
1627
+ opened_urls: list[str] = []
1628
+
1629
+ first_result = runtime.ensure_surface(
1630
+ surface="approval-center",
1631
+ approval_center_url="http://127.0.0.1:5474",
1632
+ approval_surface_policy="auto-open-once",
1633
+ open_key="dashboard",
1634
+ opener=lambda url: opened_urls.append(url) or True,
1635
+ )
1636
+ second_result = runtime.ensure_surface(
1637
+ surface="approval-center",
1638
+ approval_center_url="http://127.0.0.1:5474",
1639
+ approval_surface_policy="auto-open-once",
1640
+ open_key="dashboard",
1641
+ force_open=True,
1642
+ opener=lambda url: opened_urls.append(url) or True,
1643
+ )
1644
+
1645
+ assert first_result["opened"] is True
1646
+ assert second_result["opened"] is True
1647
+ assert opened_urls == ["http://127.0.0.1:5474", "http://127.0.0.1:5474"]
1648
+
1649
+ def test_guard_surface_runtime_force_open_overrides_disabled_policy(self, tmp_path) -> None:
1650
+ store = GuardStore(tmp_path / "guard-home")
1651
+ runtime = GuardSurfaceRuntime(store)
1652
+ opened_urls: list[str] = []
1653
+
1654
+ result = runtime.ensure_surface(
1655
+ surface="approval-center",
1656
+ approval_center_url="http://127.0.0.1:5474",
1657
+ approval_surface_policy="never-auto-open",
1658
+ open_key="dashboard",
1659
+ force_open=True,
1660
+ opener=lambda url: opened_urls.append(url) or True,
1661
+ )
1662
+
1663
+ assert result["opened"] is True
1664
+ assert result["reason"] == "opened"
1665
+ assert opened_urls == ["http://127.0.0.1:5474"]
File without changes