plugin-scanner 2.0.101__tar.gz → 2.0.103__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 (347) hide show
  1. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-layout.tsx +14 -18
  3. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-utils.ts +30 -0
  4. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-api.test.ts +141 -3
  5. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-api.ts +112 -4
  6. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-types.ts +57 -0
  7. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/pyproject.toml +1 -1
  8. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/pyproject.toml.bak +1 -1
  9. plugin_scanner-2.0.103/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +88 -0
  10. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/hermes.py +13 -1
  11. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw.py +13 -1
  12. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/commands.py +3 -4
  13. plugin_scanner-2.0.103/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
  14. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/version.py +1 -1
  15. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime.py +38 -0
  16. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_hermes_adapter.py +68 -0
  17. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_openclaw_adapter.py +68 -0
  18. plugin_scanner-2.0.101/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
  19. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/Dockerfile +0 -0
  20. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/build.sh +0 -0
  21. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/project.yaml +0 -0
  22. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  23. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.dockerignore +0 -0
  24. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/CODEOWNERS +0 -0
  25. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  26. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  28. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/dependabot.yml +0 -0
  29. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/ci.yml +0 -0
  30. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/codeql.yml +0 -0
  31. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/dependabot-uv-lock.yml +0 -0
  32. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/fuzz.yml +0 -0
  33. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/harness-smoke.yml +0 -0
  34. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/publish.yml +0 -0
  35. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/scorecard.yml +0 -0
  36. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.gitignore +0 -0
  37. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.pre-commit-hooks.yaml +0 -0
  38. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/CONTRIBUTING.md +0 -0
  39. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/Dockerfile +0 -0
  40. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/LICENSE +0 -0
  41. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/README.md +0 -0
  42. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/SECURITY.md +0 -0
  43. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/index.html +0 -0
  44. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/package.json +0 -0
  45. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/pnpm-lock.yaml +0 -0
  46. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/apple-touch-icon.png +0 -0
  47. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  48. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/brand/Logo_Whole.png +0 -0
  49. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon-16x16.png +0 -0
  50. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon-32x32.png +0 -0
  51. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon.ico +0 -0
  52. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/app.tsx +0 -0
  53. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-primitives.tsx +0 -0
  54. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/fleet-workspace.tsx +0 -0
  55. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-demo.ts +0 -0
  56. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/main.tsx +0 -0
  57. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/receipts-workspace.tsx +0 -0
  58. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/runtime-overview.tsx +0 -0
  59. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/settings-workspace.tsx +0 -0
  60. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/styles.css +0 -0
  61. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/vite-env.d.ts +0 -0
  62. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/tsconfig.json +0 -0
  63. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/vite.config.ts +0 -0
  64. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docker-requirements.txt +0 -0
  65. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/approval-audit.md +0 -0
  66. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/architecture.md +0 -0
  67. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/get-started.md +0 -0
  68. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/harness-support.md +0 -0
  69. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/local-vs-cloud.md +0 -0
  70. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/testing-matrix.md +0 -0
  71. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/mcp-trust-draft.md +0 -0
  72. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/plugin-trust-draft.md +0 -0
  73. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/skill-trust-local.md +0 -0
  74. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/fuzzers/manifest_fuzzer.py +0 -0
  75. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/requirements.txt +0 -0
  76. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/plugin-quality.v1.json +0 -0
  77. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/scan-result.v1.json +0 -0
  78. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/verify-result.v1.json +0 -0
  79. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/__init__.py +0 -0
  80. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/action_runner.py +0 -0
  81. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  82. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  83. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  84. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/claude.py +0 -0
  85. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  86. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  87. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  88. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  89. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  90. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  91. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  92. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  93. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  94. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/security.py +0 -0
  95. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  96. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/cli.py +0 -0
  97. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/cli_ui.py +0 -0
  98. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/config.py +0 -0
  99. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  100. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  101. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  102. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  103. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  104. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  105. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  106. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  107. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  108. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/github_reporting.py +0 -0
  109. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  110. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  111. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  112. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  113. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  114. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  115. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  116. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  117. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  118. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  119. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  120. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  121. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  122. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  123. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  124. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  125. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  126. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  127. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  128. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  129. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  130. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  131. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  132. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  133. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  134. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  135. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  136. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  137. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/config.py +0 -0
  138. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  139. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  140. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  141. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  142. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  143. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  144. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  145. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  146. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  147. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  148. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  149. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  150. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  151. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  152. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  153. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/incident.py +0 -0
  154. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  155. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  156. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/models.py +0 -0
  157. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  158. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  159. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/protect.py +0 -0
  160. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  161. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  162. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  163. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  164. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  165. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  166. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  167. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/risk.py +0 -0
  168. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  169. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  170. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  171. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  172. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  173. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  174. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  175. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  176. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  177. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  178. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  179. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/shims.py +0 -0
  180. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store.py +0 -0
  181. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  182. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  183. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/types.py +0 -0
  184. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  185. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  186. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  187. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  188. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  189. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/models.py +0 -0
  190. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/path_support.py +0 -0
  191. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/policy.py +0 -0
  192. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  193. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/repo_detect.py +0 -0
  194. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/reporting.py +0 -0
  195. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  196. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/registry.py +0 -0
  197. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/specs.py +0 -0
  198. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/scanner.py +0 -0
  199. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/submission.py +0 -0
  200. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/suppressions.py +0 -0
  201. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  202. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  203. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  204. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_models.py +0 -0
  205. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  206. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  207. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  208. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_specs.py +0 -0
  209. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/verification.py +0 -0
  210. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/__init__.py +0 -0
  211. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/conftest.py +0 -0
  212. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/__init__.py +0 -0
  213. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  214. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  215. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/secrets.js +0 -0
  216. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  217. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  218. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/README.md +0 -0
  219. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  220. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  221. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  222. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/code-quality-bad/evil.js +0 -0
  223. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/code-quality-bad/inject.js +0 -0
  224. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  225. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  226. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/README.md +0 -0
  227. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  228. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  229. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  230. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  231. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/.codexignore +0 -0
  232. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/LICENSE +0 -0
  233. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/README.md +0 -0
  234. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  235. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  236. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  237. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  238. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  239. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  240. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  241. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  242. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  243. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  244. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  245. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  246. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  247. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  248. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  250. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  251. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  252. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  253. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  254. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/mcp-canary-server.py +0 -0
  255. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  256. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  257. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/mit-license/LICENSE +0 -0
  258. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  259. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  260. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  261. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  262. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  263. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  264. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  265. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  266. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  267. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  268. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  269. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  270. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  271. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  272. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  273. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  274. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  275. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  276. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/LICENSE +0 -0
  277. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/README.md +0 -0
  278. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  279. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  280. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  281. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  282. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  283. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  284. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  285. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  286. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test-trust-scoring.py +0 -0
  287. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test-trust-specs.py +0 -0
  288. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_action_runner.py +0 -0
  289. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_best_practices.py +0 -0
  290. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_cisco_install_surfaces.py +0 -0
  291. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_cli.py +0 -0
  292. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_code_quality.py +0 -0
  293. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_config.py +0 -0
  294. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_coverage_remaining.py +0 -0
  295. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_ecosystems.py +0 -0
  296. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_edge_cases.py +0 -0
  297. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_final_coverage.py +0 -0
  298. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_approvals.py +0 -0
  299. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_bootstrap.py +0 -0
  300. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_capabilities.py +0 -0
  301. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_claude_adapter.py +0 -0
  302. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_cli.py +0 -0
  303. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_e2e.py +0 -0
  304. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_install.py +0 -0
  305. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_proxy.py +0 -0
  306. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_config_paths.py +0 -0
  307. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_connect_flow.py +0 -0
  308. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_consumer_mode.py +0 -0
  309. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_copilot_adapter.py +0 -0
  310. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_copilot_proxy.py +0 -0
  311. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_daemon_manager.py +0 -0
  312. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_event_schema_v1.py +0 -0
  313. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_events.py +0 -0
  314. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_launch_env.py +0 -0
  315. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_opencode_proxy.py +0 -0
  316. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_product_flow.py +0 -0
  317. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_protect.py +0 -0
  318. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_render.py +0 -0
  319. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_risk.py +0 -0
  320. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_action_harnesses.py +0 -0
  321. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_actions.py +0 -0
  322. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_decisions.py +0 -0
  323. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_signals.py +0 -0
  324. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_store_migrations.py +0 -0
  325. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_surface_server.py +0 -0
  326. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_verdicts.py +0 -0
  327. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_integration.py +0 -0
  328. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_lint_fixes.py +0 -0
  329. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_live_cisco_smoke.py +0 -0
  330. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_manifest.py +0 -0
  331. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_marketplace.py +0 -0
  332. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_mcp_security.py +0 -0
  333. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_operational_security.py +0 -0
  334. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_policy.py +0 -0
  335. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_quality_artifact.py +0 -0
  336. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_rule_registry.py +0 -0
  337. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_scanner.py +0 -0
  338. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_schema_contracts.py +0 -0
  339. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_security.py +0 -0
  340. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_security_ops.py +0 -0
  341. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_skill_security.py +0 -0
  342. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_submission.py +0 -0
  343. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_trust_scoring.py +0 -0
  344. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_trust_specs.py +0 -0
  345. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_verification.py +0 -0
  346. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_versioning.py +0 -0
  347. {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.101
3
+ Version: 2.0.103
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
@@ -35,7 +35,9 @@ import {
35
35
  buildTechnicalSummary,
36
36
  humanizeChangedFields,
37
37
  harnessDisplayName,
38
- resolveEnvelopeDisplayText
38
+ resolveDecisionV2Title,
39
+ resolveDecisionV2Detail,
40
+ resolveStoppedCommandText
39
41
  } from "./approval-center-utils";
40
42
  import type {
41
43
  GuardApprovalRequest,
@@ -782,6 +784,7 @@ function CopyCommandButton(props: { command: string }) {
782
784
 
783
785
  function BlockedActionCard(props: { item: GuardApprovalRequest }) {
784
786
  const launchText = actionLaunchText(props.item);
787
+ const decisionDetail = resolveDecisionV2Detail(props.item);
785
788
  const isBlocked = props.item.policy_action === "block";
786
789
  const bannerBg = isBlocked
787
790
  ? "bg-gradient-to-r from-brand-purple/90 to-brand-purple/75"
@@ -820,6 +823,11 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
820
823
  <p className="mt-2 text-sm leading-6 text-brand-dark/70">
821
824
  {harnessDisplayName(props.item.harness)} paused this because {buildQueueSummary(props.item).toLowerCase()}.
822
825
  </p>
826
+ {decisionDetail !== null ? (
827
+ <p className="mt-2 text-sm leading-6 text-brand-dark/80">
828
+ {decisionDetail}
829
+ </p>
830
+ ) : null}
823
831
  <div className="mt-4 rounded-[1.25rem] bg-[#090d1a] p-1 shadow-[0_14px_35px_rgba(9,13,26,0.18)]">
824
832
  <div className="flex items-center gap-1.5 border-b border-white/10 px-3 py-2">
825
833
  <span className="h-2.5 w-2.5 rounded-full bg-brand-purple" />
@@ -849,6 +857,10 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
849
857
  }
850
858
 
851
859
  function actionDisplayTitle(item: GuardApprovalRequest): string {
860
+ const v2Title = resolveDecisionV2Title(item);
861
+ if (v2Title !== null) {
862
+ return v2Title;
863
+ }
852
864
  const artifactName = displayArtifactName(item);
853
865
  if (item.artifact_type === "tool_action_request") {
854
866
  return `${harnessDisplayName(item.harness)} wants to run a tool`;
@@ -866,23 +878,7 @@ function actionDisplayTitle(item: GuardApprovalRequest): string {
866
878
  }
867
879
 
868
880
  function actionLaunchText(item: GuardApprovalRequest): string {
869
- if (item.action_envelope_json) {
870
- const envelopeText = resolveEnvelopeDisplayText(item.action_envelope_json);
871
- if (envelopeText !== null) {
872
- return envelopeText;
873
- }
874
- }
875
- if (item.launch_target?.trim()) {
876
- return item.launch_target;
877
- }
878
- if (item.launch_summary?.trim()) {
879
- const commandMatch = item.launch_summary.match(/`([^`]+)`/);
880
- if (commandMatch?.[1]) {
881
- return commandMatch[1];
882
- }
883
- return item.launch_summary;
884
- }
885
- return displayArtifactName(item);
881
+ return resolveStoppedCommandText(item);
886
882
  }
887
883
 
888
884
  function getRulePreviewText(
@@ -209,6 +209,36 @@ function capitalizeHarness(harness: string): string {
209
209
  return `${harness.charAt(0).toUpperCase()}${harness.slice(1)}`;
210
210
  }
211
211
 
212
+ export function resolveDecisionV2Title(item: GuardApprovalRequest): string | null {
213
+ const title = item.decision_v2_json?.user_title;
214
+ return title !== undefined && title.trim().length > 0 ? title : null;
215
+ }
216
+
217
+ export function resolveDecisionV2Detail(item: GuardApprovalRequest): string | null {
218
+ const detail = item.decision_v2_json?.dashboard_primary_detail;
219
+ return detail !== undefined && detail.trim().length > 0 ? detail : null;
220
+ }
221
+
222
+ export function resolveStoppedCommandText(item: GuardApprovalRequest): string {
223
+ if (item.action_envelope_json) {
224
+ const envelopeText = resolveEnvelopeDisplayText(item.action_envelope_json);
225
+ if (envelopeText !== null) {
226
+ return envelopeText;
227
+ }
228
+ }
229
+ if (item.launch_target?.trim()) {
230
+ return item.launch_target;
231
+ }
232
+ if (item.launch_summary?.trim()) {
233
+ const commandMatch = item.launch_summary.match(/`([^`]+)`/);
234
+ if (commandMatch?.[1]) {
235
+ return commandMatch[1];
236
+ }
237
+ return item.launch_summary;
238
+ }
239
+ return item.artifact_name.trim() || item.artifact_id;
240
+ }
241
+
212
242
  export function harnessDisplayName(harness: string): string {
213
243
  switch (harness) {
214
244
  case "claude-code":
@@ -1,6 +1,16 @@
1
- import { buildDemoRuntimeSnapshot, normalizeApprovalRequest, parseActionEnvelope } from "./guard-api";
2
- import { resolveEnvelopeDisplayText } from "./approval-center-utils";
3
- import type { GuardActionEnvelope, GuardApprovalRequest } from "./guard-types";
1
+ import {
2
+ buildDemoRuntimeSnapshot,
3
+ normalizeApprovalRequest,
4
+ parseActionEnvelope,
5
+ parseDecisionV2
6
+ } from "./guard-api";
7
+ import {
8
+ resolveDecisionV2Detail,
9
+ resolveDecisionV2Title,
10
+ resolveEnvelopeDisplayText,
11
+ resolveStoppedCommandText
12
+ } from "./approval-center-utils";
13
+ import type { GuardActionEnvelope, GuardApprovalRequest, GuardDecisionV2 } from "./guard-types";
4
14
 
5
15
  function assert(condition: boolean, message: string): void {
6
16
  if (!condition) {
@@ -146,3 +156,131 @@ assert(
146
156
  normalizedMalformedRequest.action_envelope_json === null,
147
157
  "T071: detail-route approval payloads normalize malformed envelopes before rendering"
148
158
  );
159
+
160
+ const BASE_DECISION_V2: GuardDecisionV2 = {
161
+ action: "block",
162
+ reason: "Credential file access detected",
163
+ user_title: "Wants to read a credential file",
164
+ user_body: "The agent is attempting to read a file that may contain secrets.",
165
+ harness_message: "BLOCKED: credential file read",
166
+ dashboard_primary_detail: "cat ~/.aws/credentials",
167
+ approval_scopes: ["artifact", "workspace"],
168
+ retry_instruction: null,
169
+ signals: [
170
+ {
171
+ signal_id: "secret:filesystem:env",
172
+ category: "secret",
173
+ severity: "high",
174
+ confidence: "strong",
175
+ detector: "guard-risk-v2",
176
+ title: "Secret file read",
177
+ plain_reason: "The action can read a credential file.",
178
+ technical_detail: null,
179
+ evidence_ref: "metadata.path_class",
180
+ redaction_level: "summary",
181
+ false_positive_hint: null,
182
+ advisory_id: null
183
+ }
184
+ ],
185
+ confidence: "strong"
186
+ };
187
+
188
+ assert(parseDecisionV2(undefined) === null, "T080: missing decision_v2_json falls back to null");
189
+ assert(parseDecisionV2(null) === null, "T080: null decision_v2_json falls back to null");
190
+ assert(parseDecisionV2({}) === null, "T080: empty object falls back to null");
191
+ assert(parseDecisionV2("block") === null, "T080: string decision_v2_json falls back to null");
192
+ assert(
193
+ parseDecisionV2({ ...BASE_DECISION_V2, action: "unknown_action" }) === null,
194
+ "T080: invalid action value falls back to null"
195
+ );
196
+ assert(
197
+ parseDecisionV2({ ...BASE_DECISION_V2, confidence: "unsure" }) === null,
198
+ "T080: invalid confidence value falls back to null"
199
+ );
200
+ assert(
201
+ parseDecisionV2({ ...BASE_DECISION_V2, approval_scopes: [42] }) === null,
202
+ "T080: non-string approval_scopes element falls back to null"
203
+ );
204
+ assert(
205
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], signal_id: 1 }] }) === null,
206
+ "T080: invalid signal_id type falls back to null"
207
+ );
208
+ assert(
209
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], severity: "extreme" }] }) === null,
210
+ "T080: invalid signal severity falls back to null"
211
+ );
212
+ assert(
213
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], redaction_level: "full" }] }) ===
214
+ null,
215
+ "T080: invalid signal redaction level falls back to null"
216
+ );
217
+
218
+ const parsedDecisionV2 = parseDecisionV2(BASE_DECISION_V2);
219
+ assert(parsedDecisionV2 !== null, "T080: valid decision_v2 object parses correctly");
220
+ assert(parsedDecisionV2?.action === "block", "T080: parsed action matches source");
221
+ assert(parsedDecisionV2?.user_title === "Wants to read a credential file", "T080: parsed user_title matches source");
222
+ assert(parsedDecisionV2?.dashboard_primary_detail === "cat ~/.aws/credentials", "T080: parsed dashboard_primary_detail matches source");
223
+ assert(parsedDecisionV2?.confidence === "strong", "T080: parsed confidence matches source");
224
+ assert(parsedDecisionV2?.retry_instruction === null, "T080: null retry_instruction preserved");
225
+ assert(parsedDecisionV2?.signals.length === 1, "T080: signals array length preserved");
226
+ assert(parsedDecisionV2?.signals[0].signal_id === "secret:filesystem:env", "T080: signal_id preserved");
227
+
228
+ const normalizedWithV2 = normalizeApprovalRequest({ ...BASE_REQUEST, decision_v2_json: BASE_DECISION_V2 });
229
+ assert(normalizedWithV2.decision_v2_json !== null, "T081: valid decision_v2_json normalizes to non-null");
230
+ assert(
231
+ normalizedWithV2.decision_v2_json?.user_title === "Wants to read a credential file",
232
+ "T081: normalized user_title preserved"
233
+ );
234
+
235
+ const normalizedMalformedV2 = normalizeApprovalRequest({
236
+ ...BASE_REQUEST,
237
+ decision_v2_json: { action: "not-a-real-action" }
238
+ });
239
+ assert(normalizedMalformedV2.decision_v2_json === null, "T081: malformed decision_v2_json normalizes to null");
240
+
241
+ const normalizedMissingV2 = normalizeApprovalRequest({ ...BASE_REQUEST });
242
+ assert(normalizedMissingV2.decision_v2_json === null, "T081: absent decision_v2_json normalizes to null");
243
+
244
+ const requestWithV2: GuardApprovalRequest = {
245
+ ...BASE_REQUEST,
246
+ decision_v2_json: BASE_DECISION_V2
247
+ };
248
+
249
+ assert(
250
+ resolveDecisionV2Title(requestWithV2) === "Wants to read a credential file",
251
+ "T082: resolveDecisionV2Title returns user_title when decision_v2_json present"
252
+ );
253
+ assert(
254
+ resolveDecisionV2Detail(requestWithV2) === "cat ~/.aws/credentials",
255
+ "T082: resolveDecisionV2Detail returns dashboard_primary_detail when decision_v2_json present"
256
+ );
257
+ assert(
258
+ resolveStoppedCommandText(requestWithV2) === "git status",
259
+ "T082: stopped command remains launch target when decision detail is present"
260
+ );
261
+ assert(
262
+ resolveDecisionV2Title(BASE_REQUEST) === null,
263
+ "T082: resolveDecisionV2Title returns null when decision_v2_json absent"
264
+ );
265
+ assert(
266
+ resolveDecisionV2Detail(BASE_REQUEST) === null,
267
+ "T082: resolveDecisionV2Detail returns null when decision_v2_json absent"
268
+ );
269
+
270
+ const requestWithWhitespaceV2Title: GuardApprovalRequest = {
271
+ ...BASE_REQUEST,
272
+ decision_v2_json: { ...BASE_DECISION_V2, user_title: " " }
273
+ };
274
+ assert(
275
+ resolveDecisionV2Title(requestWithWhitespaceV2Title) === null,
276
+ "T082: resolveDecisionV2Title returns null for whitespace-only user_title"
277
+ );
278
+
279
+ const requestWithEmptyV2Detail: GuardApprovalRequest = {
280
+ ...BASE_REQUEST,
281
+ decision_v2_json: { ...BASE_DECISION_V2, dashboard_primary_detail: "" }
282
+ };
283
+ assert(
284
+ resolveDecisionV2Detail(requestWithEmptyV2Detail) === null,
285
+ "T082: resolveDecisionV2Detail returns null for empty dashboard_primary_detail"
286
+ );
@@ -1,15 +1,27 @@
1
- import { GUARD_ACTION_TYPES } from "./guard-types";
1
+ import {
2
+ GUARD_ACTION_TYPES,
3
+ GUARD_DECISION_V2_ACTIONS,
4
+ GUARD_DECISION_V2_CONFIDENCES,
5
+ GUARD_RISK_SIGNAL_V2_CATEGORIES,
6
+ GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS,
7
+ GUARD_RISK_SIGNAL_V2_SEVERITIES
8
+ } from "./guard-types";
2
9
  import type {
3
10
  GuardActionEnvelope,
4
11
  GuardActionType,
5
12
  GuardApprovalRequest,
6
13
  GuardArtifactDiff,
14
+ GuardDecisionV2,
7
15
  GuardInventoryItem,
8
16
  GuardPolicyDecision,
9
17
  GuardReceipt,
10
18
  GuardRuntimeSnapshot,
11
19
  GuardSettingsPayload,
12
- GuardSettings
20
+ GuardSettings,
21
+ RiskSignalV2,
22
+ RiskSignalV2Category,
23
+ RiskSignalV2RedactionLevel,
24
+ RiskSignalV2Severity
13
25
  } from "./guard-types";
14
26
  import {
15
27
  getDemoDiff,
@@ -23,8 +35,9 @@ import {
23
35
  const GUARD_TOKEN_PARAM = "guard-token";
24
36
  const GUARD_DAEMON_PARAM = "guardDaemon";
25
37
 
26
- type RawGuardApprovalRequest = Omit<GuardApprovalRequest, "action_envelope_json"> & {
38
+ type RawGuardApprovalRequest = Omit<GuardApprovalRequest, "action_envelope_json" | "decision_v2_json"> & {
27
39
  action_envelope_json?: unknown;
40
+ decision_v2_json?: unknown;
28
41
  };
29
42
 
30
43
  type ApprovalRequestListPayload = {
@@ -158,6 +171,10 @@ function isStringArray(value: unknown): value is string[] {
158
171
  return Array.isArray(value) && value.every((item): item is string => typeof item === "string");
159
172
  }
160
173
 
174
+ function isNonEmptyString(value: unknown): value is string {
175
+ return typeof value === "string" && value.trim().length > 0;
176
+ }
177
+
161
178
  export function parseActionEnvelope(raw: unknown): GuardActionEnvelope | null {
162
179
  if (!isRecord(raw)) {
163
180
  return null;
@@ -231,8 +248,99 @@ export function parseActionEnvelope(raw: unknown): GuardActionEnvelope | null {
231
248
  };
232
249
  }
233
250
 
251
+ function isDecisionV2Action(value: unknown): value is GuardDecisionV2["action"] {
252
+ return typeof value === "string" && GUARD_DECISION_V2_ACTIONS.some((a) => a === value);
253
+ }
254
+
255
+ function isDecisionV2Confidence(value: unknown): value is GuardDecisionV2["confidence"] {
256
+ return typeof value === "string" && GUARD_DECISION_V2_CONFIDENCES.some((c) => c === value);
257
+ }
258
+
259
+ function isRiskSignalV2Category(value: unknown): value is RiskSignalV2Category {
260
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_CATEGORIES.some((category) => category === value);
261
+ }
262
+
263
+ function isRiskSignalV2Severity(value: unknown): value is RiskSignalV2Severity {
264
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_SEVERITIES.some((s) => s === value);
265
+ }
266
+
267
+ function isRiskSignalV2RedactionLevel(value: unknown): value is RiskSignalV2RedactionLevel {
268
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS.some((level) => level === value);
269
+ }
270
+
271
+ function isRiskSignalV2Array(value: unknown): value is RiskSignalV2[] {
272
+ if (!Array.isArray(value)) {
273
+ return false;
274
+ }
275
+ return value.every((item) => {
276
+ if (!isRecord(item)) {
277
+ return false;
278
+ }
279
+ return (
280
+ isNonEmptyString(item["signal_id"]) &&
281
+ isRiskSignalV2Category(item["category"]) &&
282
+ isRiskSignalV2Severity(item["severity"]) &&
283
+ isDecisionV2Confidence(item["confidence"]) &&
284
+ isNonEmptyString(item["detector"]) &&
285
+ isNonEmptyString(item["title"]) &&
286
+ isNonEmptyString(item["plain_reason"]) &&
287
+ isStringOrNull(item["technical_detail"]) &&
288
+ isStringOrNull(item["evidence_ref"]) &&
289
+ isRiskSignalV2RedactionLevel(item["redaction_level"]) &&
290
+ isStringOrNull(item["false_positive_hint"]) &&
291
+ isStringOrNull(item["advisory_id"])
292
+ );
293
+ });
294
+ }
295
+
296
+ export function parseDecisionV2(raw: unknown): GuardDecisionV2 | null {
297
+ if (!isRecord(raw)) {
298
+ return null;
299
+ }
300
+ const action = raw["action"];
301
+ const reason = raw["reason"];
302
+ const userTitle = raw["user_title"];
303
+ const userBody = raw["user_body"];
304
+ const harnessMessage = raw["harness_message"];
305
+ const dashboardPrimaryDetail = raw["dashboard_primary_detail"];
306
+ const approvalScopes = raw["approval_scopes"];
307
+ const retryInstruction = raw["retry_instruction"];
308
+ const signals = raw["signals"];
309
+ const confidence = raw["confidence"];
310
+ if (
311
+ !isDecisionV2Action(action) ||
312
+ !isNonEmptyString(reason) ||
313
+ !isNonEmptyString(userTitle) ||
314
+ !isNonEmptyString(userBody) ||
315
+ !isNonEmptyString(harnessMessage) ||
316
+ !isNonEmptyString(dashboardPrimaryDetail) ||
317
+ !isStringArray(approvalScopes) ||
318
+ !isStringOrNull(retryInstruction) ||
319
+ !isRiskSignalV2Array(signals) ||
320
+ !isDecisionV2Confidence(confidence)
321
+ ) {
322
+ return null;
323
+ }
324
+ return {
325
+ action,
326
+ reason,
327
+ user_title: userTitle,
328
+ user_body: userBody,
329
+ harness_message: harnessMessage,
330
+ dashboard_primary_detail: dashboardPrimaryDetail,
331
+ approval_scopes: approvalScopes,
332
+ retry_instruction: retryInstruction,
333
+ signals,
334
+ confidence
335
+ };
336
+ }
337
+
234
338
  export function normalizeApprovalRequest(item: RawGuardApprovalRequest): GuardApprovalRequest {
235
- return { ...item, action_envelope_json: parseActionEnvelope(item.action_envelope_json) };
339
+ return {
340
+ ...item,
341
+ action_envelope_json: parseActionEnvelope(item.action_envelope_json),
342
+ decision_v2_json: parseDecisionV2(item.decision_v2_json)
343
+ };
236
344
  }
237
345
 
238
346
  function normalizeApprovalRequests(items: RawGuardApprovalRequest[] | null | undefined): GuardApprovalRequest[] {
@@ -15,6 +15,62 @@ export const GUARD_ACTION_TYPES = [
15
15
 
16
16
  export type GuardActionType = (typeof GUARD_ACTION_TYPES)[number];
17
17
 
18
+ export const GUARD_DECISION_V2_ACTIONS = ["allow", "warn", "ask", "block"] as const;
19
+ export const GUARD_DECISION_V2_CONFIDENCES = ["weak", "likely", "strong"] as const;
20
+ export const GUARD_RISK_SIGNAL_V2_CATEGORIES = [
21
+ "secret",
22
+ "network",
23
+ "prompt",
24
+ "mcp",
25
+ "skill",
26
+ "supply_chain",
27
+ "encoded",
28
+ "persistence",
29
+ "bypass",
30
+ "false_positive",
31
+ "filesystem",
32
+ "execution",
33
+ "publisher",
34
+ "policy",
35
+ "provenance"
36
+ ] as const;
37
+ export const GUARD_RISK_SIGNAL_V2_SEVERITIES = ["info", "low", "medium", "high", "critical"] as const;
38
+ export const GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS = ["none", "summary", "redacted"] as const;
39
+
40
+ export type GuardDecisionV2Action = (typeof GUARD_DECISION_V2_ACTIONS)[number];
41
+ export type GuardDecisionV2Confidence = (typeof GUARD_DECISION_V2_CONFIDENCES)[number];
42
+ export type RiskSignalV2Category = (typeof GUARD_RISK_SIGNAL_V2_CATEGORIES)[number];
43
+ export type RiskSignalV2Severity = (typeof GUARD_RISK_SIGNAL_V2_SEVERITIES)[number];
44
+ export type RiskSignalV2RedactionLevel = (typeof GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS)[number];
45
+
46
+ export type RiskSignalV2 = {
47
+ signal_id: string;
48
+ category: RiskSignalV2Category;
49
+ severity: RiskSignalV2Severity;
50
+ confidence: GuardDecisionV2Confidence;
51
+ detector: string;
52
+ title: string;
53
+ plain_reason: string;
54
+ technical_detail: string | null;
55
+ evidence_ref: string | null;
56
+ redaction_level: RiskSignalV2RedactionLevel;
57
+ false_positive_hint: string | null;
58
+ advisory_id: string | null;
59
+ };
60
+
61
+ export type GuardDecisionV2 = {
62
+ action: GuardDecisionV2Action;
63
+ reason: string;
64
+ user_title: string;
65
+ user_body: string;
66
+ harness_message: string;
67
+ dashboard_primary_detail: string;
68
+ approval_scopes: string[];
69
+ retry_instruction: string | null;
70
+ signals: RiskSignalV2[];
71
+ confidence: GuardDecisionV2Confidence;
72
+ };
73
+
18
74
  export type GuardActionEnvelope = {
19
75
  schema_version: number;
20
76
  action_id: string;
@@ -74,6 +130,7 @@ export type GuardApprovalRequest = {
74
130
  created_at: string;
75
131
  resolved_at: string | null;
76
132
  action_envelope_json?: GuardActionEnvelope | null;
133
+ decision_v2_json?: GuardDecisionV2 | null;
77
134
  };
78
135
 
79
136
  export type GuardRuntimeState = {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.101"
7
+ version = "2.0.103"
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.101"
7
+ version = "2.0.103"
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"
@@ -0,0 +1,88 @@
1
+ """Guard Cloud agent identity hints for local harness adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import sqlite3
7
+ from pathlib import Path
8
+
9
+ from .base import HarnessContext
10
+
11
+ _SERVICE_RUNTIME_PROFILE_STATE_KEY = "service_runtime_profile"
12
+ _PROFILE_FIELDS = (
13
+ "runtime",
14
+ "label",
15
+ "workspace",
16
+ "surface",
17
+ "client_name",
18
+ "client_title",
19
+ "client_version",
20
+ "agent_id",
21
+ "principal_id",
22
+ )
23
+ _ENV_FIELDS = {
24
+ "runtime": "RUNTIME",
25
+ "label": "LABEL",
26
+ "workspace": "WORKSPACE",
27
+ "agent_id": "AGENT_ID",
28
+ "principal_id": "PRINCIPAL_ID",
29
+ }
30
+
31
+
32
+ def cloud_agent_identity_hints(
33
+ context: HarnessContext,
34
+ *,
35
+ runtime: str,
36
+ ) -> dict[str, str] | None:
37
+ payload = _read_service_runtime_profile(context.guard_home / "guard.db")
38
+ if payload is None or _string_field(payload, "runtime") != runtime:
39
+ return None
40
+ hints = {field: value for field in _PROFILE_FIELDS if (value := _string_field(payload, field)) is not None}
41
+ return hints if hints else None
42
+
43
+
44
+ def cloud_agent_identity_environment(
45
+ identity: object,
46
+ *,
47
+ prefix: str,
48
+ ) -> dict[str, str]:
49
+ if not isinstance(identity, dict):
50
+ return {}
51
+ env: dict[str, str] = {}
52
+ for field, suffix in _ENV_FIELDS.items():
53
+ value = identity.get(field)
54
+ if isinstance(value, str) and value:
55
+ env[f"{prefix}_GUARD_CLOUD_{suffix}"] = value
56
+ return env
57
+
58
+
59
+ def _read_service_runtime_profile(db_path: Path) -> dict[str, object] | None:
60
+ if not db_path.exists():
61
+ return None
62
+ try:
63
+ db_uri = f"{db_path.resolve().as_uri()}?mode=ro"
64
+ connection = sqlite3.connect(db_uri, uri=True)
65
+ try:
66
+ row = connection.execute(
67
+ "select payload_json from sync_state where state_key = ?",
68
+ (_SERVICE_RUNTIME_PROFILE_STATE_KEY,),
69
+ ).fetchone()
70
+ finally:
71
+ connection.close()
72
+ except (OSError, sqlite3.Error):
73
+ return None
74
+ if row is None:
75
+ return None
76
+ try:
77
+ payload = json.loads(str(row[0]))
78
+ except json.JSONDecodeError:
79
+ return None
80
+ return payload if isinstance(payload, dict) else None
81
+
82
+
83
+ def _string_field(payload: dict[str, object], field: str) -> str | None:
84
+ value = payload.get(field)
85
+ if not isinstance(value, str):
86
+ return None
87
+ stripped = value.strip()
88
+ return stripped or None
@@ -16,6 +16,7 @@ from pathlib import Path
16
16
  from ..models import GuardArtifact, HarnessDetection
17
17
  from ..shims import install_guard_shim, remove_guard_shim
18
18
  from .base import HarnessAdapter, HarnessContext, _command_available, _json_payload, _run_command_probe
19
+ from .cloud_identity import cloud_agent_identity_environment, cloud_agent_identity_hints
19
20
 
20
21
  # Optional: PyYAML is preferred when available for robust YAML parsing.
21
22
  # The adapter works without it via a line-based fallback parser.
@@ -83,6 +84,7 @@ class HermesHarnessAdapter(HarnessAdapter):
83
84
  )
84
85
  source_configs = _load_mcp_server_sources(context.home_dir / ".hermes")
85
86
  overlay_servers = _overlay_servers(context=context, source_configs=source_configs)
87
+ cloud_identity = cloud_agent_identity_hints(context, runtime=self.harness)
86
88
  overlay_path.write_text(json.dumps(overlay_servers, indent=2) + "\n", encoding="utf-8")
87
89
  pretool_path.write_text(
88
90
  json.dumps(_pretool_payload(context=context), indent=2) + "\n",
@@ -109,6 +111,8 @@ class HermesHarnessAdapter(HarnessAdapter):
109
111
  *[str(note) for note in shim_manifest.get("notes", [])],
110
112
  ],
111
113
  }
114
+ if cloud_identity is not None:
115
+ manifest["cloud_agent_identity"] = cloud_identity
112
116
  manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
113
117
  return manifest
114
118
 
@@ -147,10 +151,17 @@ class HermesHarnessAdapter(HarnessAdapter):
147
151
  pretool_path = manifest.get("pretool_hook_path")
148
152
  if not isinstance(overlay_path, str) or not isinstance(pretool_path, str):
149
153
  return {}
150
- return {
154
+ environment = {
151
155
  "HERMES_GUARD_MCP_OVERLAY_PATH": overlay_path,
152
156
  "HERMES_GUARD_PRETOOL_PATH": pretool_path,
153
157
  }
158
+ environment.update(
159
+ cloud_agent_identity_environment(
160
+ cloud_agent_identity_hints(context, runtime=self.harness),
161
+ prefix="HERMES",
162
+ )
163
+ )
164
+ return environment
154
165
 
155
166
  def runtime_probe(self, context: HarnessContext) -> dict[str, object] | None:
156
167
  manifest = _json_payload(_managed_root(context) / "manifest.json")
@@ -165,6 +176,7 @@ class HermesHarnessAdapter(HarnessAdapter):
165
176
  and isinstance(pretool_path, str)
166
177
  and Path(pretool_path).exists()
167
178
  ),
179
+ "cloud_agent_identity_configured": bool(cloud_agent_identity_hints(context, runtime=self.harness)),
168
180
  }
169
181
 
170
182
  def approval_flow(self, *, managed_install: dict[str, object] | None = None) -> dict[str, object]: