plugin-scanner 2.0.107__tar.gz → 2.0.109__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.
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/PKG-INFO +20 -9
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/README.md +19 -8
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/get-started.md +24 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/testing-matrix.md +10 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/pyproject.toml +1 -1
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/commands.py +56 -9
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/render.py +117 -51
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +124 -2
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_cli.py +36 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_cli.py +157 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_product_flow.py +11 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_risk.py +56 -1
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime.py +209 -4
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime_detectors.py +3 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.dockerignore +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.gitignore +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/Dockerfile +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/requirements.txt +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.109
|
|
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
|
|
@@ -302,33 +302,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
302
302
|
|
|
303
303
|
```bash
|
|
304
304
|
# Scan a plugin directory
|
|
305
|
-
plugin-scanner ./my-plugin
|
|
305
|
+
plugin-scanner scan ./my-plugin
|
|
306
306
|
|
|
307
307
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
308
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
308
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
309
309
|
|
|
310
310
|
# Scan only Claude package surfaces
|
|
311
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
311
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
312
312
|
|
|
313
313
|
# List supported ecosystems
|
|
314
314
|
plugin-scanner --list-ecosystems
|
|
315
315
|
|
|
316
316
|
# Output JSON
|
|
317
|
-
plugin-scanner ./my-plugin --json
|
|
317
|
+
plugin-scanner scan ./my-plugin --format json
|
|
318
318
|
|
|
319
319
|
# Write a SARIF report for GitHub code scanning
|
|
320
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
320
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
321
321
|
|
|
322
322
|
# Fail CI on findings at or above high severity
|
|
323
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
323
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
324
324
|
|
|
325
325
|
# Require Cisco skill scanning with a strict policy
|
|
326
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
326
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
327
327
|
|
|
328
328
|
# Require optional Cisco MCP static analysis
|
|
329
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
329
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
333
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
334
|
+
|
|
335
|
+
| Need | Command | Output contract |
|
|
336
|
+
| :--- | :--- | :--- |
|
|
337
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
338
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
339
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
340
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
341
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
342
|
+
|
|
332
343
|
## Quality Suite Commands
|
|
333
344
|
|
|
334
345
|
```bash
|
|
@@ -262,33 +262,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
262
262
|
|
|
263
263
|
```bash
|
|
264
264
|
# Scan a plugin directory
|
|
265
|
-
plugin-scanner ./my-plugin
|
|
265
|
+
plugin-scanner scan ./my-plugin
|
|
266
266
|
|
|
267
267
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
268
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
268
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
269
269
|
|
|
270
270
|
# Scan only Claude package surfaces
|
|
271
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
271
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
272
272
|
|
|
273
273
|
# List supported ecosystems
|
|
274
274
|
plugin-scanner --list-ecosystems
|
|
275
275
|
|
|
276
276
|
# Output JSON
|
|
277
|
-
plugin-scanner ./my-plugin --json
|
|
277
|
+
plugin-scanner scan ./my-plugin --format json
|
|
278
278
|
|
|
279
279
|
# Write a SARIF report for GitHub code scanning
|
|
280
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
280
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
281
281
|
|
|
282
282
|
# Fail CI on findings at or above high severity
|
|
283
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
283
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
284
284
|
|
|
285
285
|
# Require Cisco skill scanning with a strict policy
|
|
286
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
286
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
287
287
|
|
|
288
288
|
# Require optional Cisco MCP static analysis
|
|
289
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
289
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
290
290
|
```
|
|
291
291
|
|
|
292
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
293
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
294
|
+
|
|
295
|
+
| Need | Command | Output contract |
|
|
296
|
+
| :--- | :--- | :--- |
|
|
297
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
298
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
299
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
300
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
301
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
302
|
+
|
|
292
303
|
## Quality Suite Commands
|
|
293
304
|
|
|
294
305
|
```bash
|
|
@@ -76,6 +76,30 @@ Use it when you want to protect a harness before local MCP servers, skills, hook
|
|
|
76
76
|
hol-guard device rotate
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
## Which command should I use?
|
|
80
|
+
|
|
81
|
+
| Situation | Command | What it answers |
|
|
82
|
+
| :--- | :--- | :--- |
|
|
83
|
+
| I need the current protection posture | `hol-guard status` | What is Guard watching, is sync connected, and what is the next action? |
|
|
84
|
+
| I need setup or runtime troubleshooting | `hol-guard doctor <harness>` | Why is this harness or Guard runtime not behaving correctly? |
|
|
85
|
+
| A launch was blocked or changed | `hol-guard diff <harness>` | What changed since the last recorded snapshot? |
|
|
86
|
+
| I need to resolve a queued block | `hol-guard approvals` | Which requests are waiting, and how do I approve or deny them? |
|
|
87
|
+
| I need decision history | `hol-guard receipts` | What decisions did Guard record locally? |
|
|
88
|
+
| I need the tracked catalog | `hol-guard inventory` | Which artifacts are currently tracked and present? |
|
|
89
|
+
| I need an exportable evidence artifact | `hol-guard abom` | What local AI-BOM can I attach to an audit or handoff? |
|
|
90
|
+
| I need the chronological log | `hol-guard events` | What happened over time on this machine? |
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
| Symptom | Start here | Then try |
|
|
95
|
+
| :--- | :--- | :--- |
|
|
96
|
+
| Guard did not find my harness | `hol-guard detect --json` | `hol-guard doctor <harness> --json` for adapter-specific warnings |
|
|
97
|
+
| `hol-guard run` paused a launch | `hol-guard diff <harness>` | `hol-guard approvals`, then retry `hol-guard run <harness>` |
|
|
98
|
+
| I approved a prompt and want proof | `hol-guard receipts` | `hol-guard explain <artifact-id>` for the latest receipt and diff context |
|
|
99
|
+
| I need audit or handoff evidence | `hol-guard inventory` | `hol-guard abom --format json` for machine-readable export |
|
|
100
|
+
| I need to understand recent activity | `hol-guard events` | Use `--name <event>` to filter a noisy local timeline |
|
|
101
|
+
| Cloud sync or pairing looks wrong | `hol-guard status` | `hol-guard connect` or `hol-guard sync --json` depending on the status output |
|
|
102
|
+
|
|
79
103
|
## Evidence-first decisions
|
|
80
104
|
|
|
81
105
|
Guard now scores local decisions from structured evidence, not only string heuristics. Each changed artifact carries:
|
|
@@ -10,6 +10,8 @@ Automated coverage in this phase includes:
|
|
|
10
10
|
- consumer-mode JSON contract generation against scanner fixtures
|
|
11
11
|
- local HTTP sync against a live in-process server instead of mocked transport
|
|
12
12
|
- scheduled self-hosted harness smoke through `.github/workflows/harness-smoke.yml`
|
|
13
|
+
- CLI DX contract tests for summary-first `run`, `explain`, `doctor`, `scan`, `lint`, and `verify` output
|
|
14
|
+
- scanner command consistency tests for nonexistent target handling across `scan`, `lint`, `verify`, `doctor`, and `submit`
|
|
13
15
|
|
|
14
16
|
Manual verification should include:
|
|
15
17
|
|
|
@@ -32,6 +34,14 @@ Manual verification should include:
|
|
|
32
34
|
- `hol-guard install codex`
|
|
33
35
|
- `hol-guard run codex --dry-run --default-action allow --json`
|
|
34
36
|
- `hol-guard receipts`
|
|
37
|
+
- `hol-guard explain codex:project:<artifact-name>`
|
|
38
|
+
- `hol-guard diff codex`
|
|
39
|
+
- `hol-guard events`
|
|
40
|
+
- `hol-guard abom`
|
|
41
|
+
- `plugin-scanner scan tests/fixtures/good-plugin --format json`
|
|
42
|
+
- `plugin-scanner lint tests/fixtures/good-plugin --format json`
|
|
43
|
+
- `plugin-scanner verify tests/fixtures/good-plugin --format json`
|
|
44
|
+
- `plugin-scanner doctor tests/fixtures/good-plugin --component mcp --bundle dist/doctor.zip`
|
|
35
45
|
- `codex mcp list`
|
|
36
46
|
- `cursor-agent mcp list`
|
|
37
47
|
- `antigravity --help`
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plugin-scanner"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.109"
|
|
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.
|
|
7
|
+
version = "2.0.109"
|
|
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"
|
{plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -97,6 +97,7 @@ from ..runtime.secret_file_requests import (
|
|
|
97
97
|
extract_sensitive_tool_action_request,
|
|
98
98
|
is_explicitly_benign_tool_action_request,
|
|
99
99
|
)
|
|
100
|
+
from ..runtime.secret_sensitivity import SecretContentMatch, classify_secret_content
|
|
100
101
|
from ..runtime.surface_server import GuardSurfaceRuntime
|
|
101
102
|
from ..store import GuardStore
|
|
102
103
|
from .approval_commands import add_approval_parser, run_approval_command
|
|
@@ -149,7 +150,15 @@ _GUARD_HELP_GROUPS = (
|
|
|
149
150
|
" bootstrap Detect, install, and launch the approval center\n"
|
|
150
151
|
" install Enable Guard management for a harness\n"
|
|
151
152
|
" uninstall Disable Guard management for a harness\n"
|
|
152
|
-
" update Update hol-guard in the current environment"
|
|
153
|
+
" update Update hol-guard in the current environment\n"
|
|
154
|
+
"\n"
|
|
155
|
+
"Command selection:\n"
|
|
156
|
+
" Use status for current posture and the next safe step\n"
|
|
157
|
+
" Use doctor for setup and runtime probes\n"
|
|
158
|
+
" Use diff for changed artifacts after a blocked launch\n"
|
|
159
|
+
" Use explain for detailed artifact evidence\n"
|
|
160
|
+
" Use approvals for queued decisions and receipts for audit history\n"
|
|
161
|
+
" Use events for the local timeline"
|
|
153
162
|
)
|
|
154
163
|
|
|
155
164
|
|
|
@@ -3962,10 +3971,6 @@ def _hook_runtime_artifact(
|
|
|
3962
3971
|
)
|
|
3963
3972
|
|
|
3964
3973
|
|
|
3965
|
-
_CODEX_SECRET_OUTPUT_PATTERN = re.compile(
|
|
3966
|
-
r"(?i)(?:fake[_-]?credential|fake[_-]?secret|"
|
|
3967
|
-
r"(?:api[_-]?key|auth[_-]?token|credential|npm[_-]?token|private[_-]?key|secret|token|password)\s*[:=])"
|
|
3968
|
-
)
|
|
3969
3974
|
_CODEX_PROMPT_SECRET_KEY_MARKERS = ("TOKEN", "SECRET", "PASSWORD", "PASS", "API_KEY", "API-KEY", "AUTH", "CREDENTIAL")
|
|
3970
3975
|
_CODEX_TOOL_RESPONSE_MAX_DEPTH = 5
|
|
3971
3976
|
_CODEX_TOOL_RESPONSE_TEXT_LIMIT = 20000
|
|
@@ -3980,13 +3985,19 @@ def _codex_post_tool_output_artifact(
|
|
|
3980
3985
|
cwd: Path | None,
|
|
3981
3986
|
) -> GuardArtifact | None:
|
|
3982
3987
|
response_text = _collect_codex_tool_response_text(payload.get("tool_response"))
|
|
3983
|
-
|
|
3988
|
+
content_matches = classify_secret_content(response_text)
|
|
3989
|
+
if not content_matches:
|
|
3984
3990
|
return None
|
|
3985
3991
|
tool_name = _coalesce_string(payload.get("tool_name"), "Bash")
|
|
3986
3992
|
command_text = _codex_post_tool_command_text(payload)
|
|
3987
3993
|
if not command_text:
|
|
3988
3994
|
command_text = tool_name
|
|
3989
|
-
if
|
|
3995
|
+
if _codex_source_inspection_can_skip_secret_output(
|
|
3996
|
+
command_text=command_text,
|
|
3997
|
+
response_text=response_text,
|
|
3998
|
+
content_matches=content_matches,
|
|
3999
|
+
cwd=cwd,
|
|
4000
|
+
):
|
|
3990
4001
|
return None
|
|
3991
4002
|
fingerprint = hashlib.sha256(
|
|
3992
4003
|
json.dumps(
|
|
@@ -4109,6 +4120,10 @@ _CODEX_SOURCE_SEARCH_EXTENSIONS = frozenset(
|
|
|
4109
4120
|
".yml",
|
|
4110
4121
|
}
|
|
4111
4122
|
)
|
|
4123
|
+
_CODEX_BENIGN_SOURCE_DOTFILES = frozenset({".nvmrc"})
|
|
4124
|
+
_CODEX_BENIGN_SECRET_FIXTURE_ASSIGNMENT_PATTERN = re.compile(
|
|
4125
|
+
r"(?i)\s*fake[_-]?(?:credential|secret|token)\s*[:=]\s*(?:\"[^\r\n\"]+\"|'[^\r\n']+'|[^\s\"',}]+)\s*"
|
|
4126
|
+
)
|
|
4112
4127
|
_CODEX_SENSITIVE_SEARCH_BASENAMES = frozenset(
|
|
4113
4128
|
{
|
|
4114
4129
|
".aws",
|
|
@@ -4127,6 +4142,35 @@ _CODEX_SENSITIVE_SEARCH_BASENAMES = frozenset(
|
|
|
4127
4142
|
_CODEX_SED_PRINT_SCRIPT_PATTERN = re.compile(r"^\s*(?:\$|\d+)?(?:\s*,\s*(?:\$|\d+))?p\s*$")
|
|
4128
4143
|
|
|
4129
4144
|
|
|
4145
|
+
def _codex_source_inspection_can_skip_secret_output(
|
|
4146
|
+
*,
|
|
4147
|
+
command_text: str,
|
|
4148
|
+
response_text: str,
|
|
4149
|
+
content_matches: tuple[SecretContentMatch, ...],
|
|
4150
|
+
cwd: Path | None,
|
|
4151
|
+
) -> bool:
|
|
4152
|
+
if not _codex_command_is_read_only_source_inspection(command_text, cwd=cwd):
|
|
4153
|
+
return False
|
|
4154
|
+
if any(match.sensitivity != "medium" for match in content_matches):
|
|
4155
|
+
return False
|
|
4156
|
+
if _codex_command_references_benign_source_dotfile(command_text):
|
|
4157
|
+
return _codex_output_is_only_benign_secret_fixture(response_text)
|
|
4158
|
+
return True
|
|
4159
|
+
|
|
4160
|
+
|
|
4161
|
+
def _codex_output_is_only_benign_secret_fixture(response_text: str) -> bool:
|
|
4162
|
+
lines = [line for line in response_text.splitlines() if line.strip()]
|
|
4163
|
+
return bool(lines) and all(_CODEX_BENIGN_SECRET_FIXTURE_ASSIGNMENT_PATTERN.fullmatch(line) for line in lines)
|
|
4164
|
+
|
|
4165
|
+
|
|
4166
|
+
def _codex_command_references_benign_source_dotfile(command_text: str) -> bool:
|
|
4167
|
+
try:
|
|
4168
|
+
parts = shlex.split(command_text)
|
|
4169
|
+
except ValueError:
|
|
4170
|
+
return False
|
|
4171
|
+
return any(Path(part).name.lower() in _CODEX_BENIGN_SOURCE_DOTFILES for part in parts)
|
|
4172
|
+
|
|
4173
|
+
|
|
4130
4174
|
def _codex_command_is_read_only_source_inspection(command_text: str, *, cwd: Path | None) -> bool:
|
|
4131
4175
|
command = command_text.strip()
|
|
4132
4176
|
if not command:
|
|
@@ -4644,13 +4688,16 @@ def _codex_search_target_is_source_like(target: str, *, cwd: Path | None) -> boo
|
|
|
4644
4688
|
lowered_parts = [part.lower() for part in parts]
|
|
4645
4689
|
if any(part in _CODEX_SENSITIVE_SEARCH_BASENAMES for part in lowered_parts):
|
|
4646
4690
|
return False
|
|
4647
|
-
if
|
|
4691
|
+
hidden_parts = [part for part in lowered_parts if part.startswith(".")]
|
|
4692
|
+
if hidden_parts and not all(part in _CODEX_BENIGN_SOURCE_DOTFILES for part in hidden_parts):
|
|
4648
4693
|
return False
|
|
4649
4694
|
normalized = "/".join(parts)
|
|
4650
4695
|
if normalized in {prefix.rstrip("/") for prefix in _CODEX_SOURCE_SEARCH_PREFIXES}:
|
|
4651
4696
|
return True
|
|
4652
4697
|
if any(normalized.startswith(prefix) for prefix in _CODEX_SOURCE_SEARCH_PREFIXES):
|
|
4653
4698
|
return True
|
|
4699
|
+
if Path(stripped).name.lower() in _CODEX_BENIGN_SOURCE_DOTFILES:
|
|
4700
|
+
return True
|
|
4654
4701
|
return Path(stripped).suffix.lower() in _CODEX_SOURCE_SEARCH_EXTENSIONS
|
|
4655
4702
|
|
|
4656
4703
|
|
|
@@ -4745,7 +4792,7 @@ def _codex_prompt_credential_file_artifact(
|
|
|
4745
4792
|
content = handle.read(_PROMPT_CONTENT_SCAN_MAX_BYTES).decode("utf-8", errors="ignore")
|
|
4746
4793
|
except OSError:
|
|
4747
4794
|
continue
|
|
4748
|
-
if
|
|
4795
|
+
if not classify_secret_content(content):
|
|
4749
4796
|
continue
|
|
4750
4797
|
normalized_path = str(path)
|
|
4751
4798
|
fingerprint = hashlib.sha256(
|
{plugin_scanner-2.0.107 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/render.py
RENAMED
|
@@ -285,37 +285,37 @@ def _render_doctor(console: Console, payload: dict[str, object]) -> None:
|
|
|
285
285
|
)
|
|
286
286
|
adapters = _coerce_dict_list(payload.get("adapters"))
|
|
287
287
|
console.print(_build_harness_table(adapters))
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
summary.add_row("
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
288
|
+
else:
|
|
289
|
+
warnings = _coerce_string_list(payload.get("warnings"))
|
|
290
|
+
summary = Table.grid(padding=(0, 1))
|
|
291
|
+
summary.add_row("Harness", f"[bold]{payload.get('harness', 'unknown')}[/bold]")
|
|
292
|
+
summary.add_row("Installed", _bool_label(bool(payload.get("installed"))))
|
|
293
|
+
summary.add_row("Command", _bool_label(bool(payload.get("command_available"))))
|
|
294
|
+
summary.add_row("Artifacts", str(len(_coerce_dict_list(payload.get("artifacts")))))
|
|
295
|
+
registry = payload.get("runtime_detector_registry")
|
|
296
|
+
if isinstance(registry, dict):
|
|
297
|
+
registry_state = "enabled" if bool(registry.get("enabled")) else "disabled"
|
|
298
|
+
timeout_ms = registry.get("timeout_ms")
|
|
299
|
+
summary.add_row("Detector registry", f"{registry_state}, {timeout_ms} ms")
|
|
300
|
+
summary.add_row("Warnings", str(len(warnings)))
|
|
301
|
+
console.print(Panel(summary, title="Guard doctor", border_style="cyan"))
|
|
302
|
+
if warnings:
|
|
303
|
+
warning_text = "\n".join(
|
|
304
|
+
textwrap.fill(
|
|
305
|
+
f"• {warning}",
|
|
306
|
+
width=72,
|
|
307
|
+
subsequent_indent=" ",
|
|
308
|
+
)
|
|
309
|
+
for warning in warnings
|
|
309
310
|
)
|
|
310
|
-
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.print(_build_artifact_table(artifacts))
|
|
311
|
+
console.print(Panel(Text(warning_text), title="Attention", border_style="yellow"))
|
|
312
|
+
runtime_probe = payload.get("runtime_probe")
|
|
313
|
+
if isinstance(runtime_probe, dict):
|
|
314
|
+
console.print(_build_runtime_probe_panel(runtime_probe))
|
|
315
|
+
artifacts = _coerce_dict_list(payload.get("artifacts"))
|
|
316
|
+
if artifacts:
|
|
317
|
+
console.print(_build_artifact_table(artifacts))
|
|
318
|
+
console.print(_build_diagnostic_command_panel())
|
|
319
319
|
|
|
320
320
|
|
|
321
321
|
def _render_run(console: Console, payload: dict[str, object]) -> None:
|
|
@@ -481,7 +481,11 @@ def _render_advisories(console: Console, payload: dict[str, object]) -> None:
|
|
|
481
481
|
border_style="cyan",
|
|
482
482
|
)
|
|
483
483
|
)
|
|
484
|
-
|
|
484
|
+
console.print(_build_advisory_table(items))
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _build_advisory_table(items: list[dict[str, object]], *, title: str | None = None) -> Table:
|
|
488
|
+
table = Table(title=title, box=box.SIMPLE_HEAVY, show_header=True)
|
|
485
489
|
table.add_column("Publisher", style="bold")
|
|
486
490
|
table.add_column("Severity")
|
|
487
491
|
table.add_column("Headline")
|
|
@@ -493,7 +497,7 @@ def _render_advisories(console: Console, payload: dict[str, object]) -> None:
|
|
|
493
497
|
str(item.get("headline") or item.get("cache_key") or "advisory"),
|
|
494
498
|
str(item.get("updated_at") or "unknown"),
|
|
495
499
|
)
|
|
496
|
-
|
|
500
|
+
return table
|
|
497
501
|
|
|
498
502
|
|
|
499
503
|
def _render_events(console: Console, payload: dict[str, object]) -> None:
|
|
@@ -1077,6 +1081,40 @@ def _render_scan(console: Console, payload: dict[str, object]) -> None:
|
|
|
1077
1081
|
_render_cisco_evidence(console, payload)
|
|
1078
1082
|
|
|
1079
1083
|
|
|
1084
|
+
def _render_explain(console: Console, payload: dict[str, object]) -> None:
|
|
1085
|
+
advisories = _coerce_dict_list(payload.get("advisories"))
|
|
1086
|
+
if "artifact_snapshot" in payload:
|
|
1087
|
+
console.print(Panel(_build_consumer_summary_table(payload), title="Path evidence", border_style="cyan"))
|
|
1088
|
+
_render_consumer_evidence_panels(console, payload)
|
|
1089
|
+
_render_cisco_evidence(console, payload)
|
|
1090
|
+
if advisories:
|
|
1091
|
+
console.print(_build_advisory_table(advisories, title="Matching advisories"))
|
|
1092
|
+
return
|
|
1093
|
+
artifact = payload.get("artifact")
|
|
1094
|
+
if not isinstance(artifact, dict):
|
|
1095
|
+
_render_fallback(console, payload)
|
|
1096
|
+
return
|
|
1097
|
+
latest_receipt = payload.get("latest_receipt")
|
|
1098
|
+
latest_diff = payload.get("latest_diff")
|
|
1099
|
+
body = Table.grid(padding=(0, 1))
|
|
1100
|
+
body.add_row("Artifact", str(artifact.get("artifact_name") or artifact.get("artifact_id") or "unknown"))
|
|
1101
|
+
body.add_row("Harness", str(artifact.get("harness") or "unknown"))
|
|
1102
|
+
body.add_row("Type", str(artifact.get("artifact_type") or "artifact"))
|
|
1103
|
+
body.add_row("Scope", str(artifact.get("source_scope") or "unknown"))
|
|
1104
|
+
body.add_row("Present", _bool_label(bool(artifact.get("present"))))
|
|
1105
|
+
if isinstance(latest_receipt, dict):
|
|
1106
|
+
body.add_row("Latest decision", _action_text(str(latest_receipt.get("policy_decision") or "warn")))
|
|
1107
|
+
body.add_row("Receipt time", str(latest_receipt.get("timestamp") or "unknown"))
|
|
1108
|
+
if isinstance(latest_diff, dict):
|
|
1109
|
+
changed_fields = ", ".join(_coerce_string_list(latest_diff.get("changed_fields"))) or "no field changes"
|
|
1110
|
+
body.add_row("Latest diff", changed_fields)
|
|
1111
|
+
body.add_row("Current hash", str(latest_diff.get("current_hash") or "unknown"))
|
|
1112
|
+
body.add_row("Advisories", str(len(advisories)))
|
|
1113
|
+
console.print(Panel(body, title="Guard artifact evidence", border_style="cyan"))
|
|
1114
|
+
if advisories:
|
|
1115
|
+
console.print(_build_advisory_table(advisories, title="Matching advisories"))
|
|
1116
|
+
|
|
1117
|
+
|
|
1080
1118
|
def _render_preflight(console: Console, payload: dict[str, object]) -> None:
|
|
1081
1119
|
install_verdict = payload.get("install_verdict")
|
|
1082
1120
|
install_target = payload.get("install_target")
|
|
@@ -1209,6 +1247,21 @@ def _build_steps_panel(steps: list[dict[str, object]]) -> Panel:
|
|
|
1209
1247
|
return Panel("\n\n".join(lines), title="Next steps", border_style="green")
|
|
1210
1248
|
|
|
1211
1249
|
|
|
1250
|
+
def _build_diagnostic_command_panel() -> Panel:
|
|
1251
|
+
return Panel(
|
|
1252
|
+
"\n".join(
|
|
1253
|
+
(
|
|
1254
|
+
"Use status for current posture: hol-guard status",
|
|
1255
|
+
"Use doctor for setup and runtime probes: hol-guard doctor <harness>",
|
|
1256
|
+
"Use diff for changed artifacts: hol-guard diff <harness>",
|
|
1257
|
+
"Use events for the local timeline: hol-guard events",
|
|
1258
|
+
)
|
|
1259
|
+
),
|
|
1260
|
+
title="Which diagnostic command?",
|
|
1261
|
+
border_style="blue",
|
|
1262
|
+
)
|
|
1263
|
+
|
|
1264
|
+
|
|
1212
1265
|
def _render_harness_detail(console: Console, detection: dict[str, object]) -> None:
|
|
1213
1266
|
artifacts = _coerce_dict_list(detection.get("artifacts"))
|
|
1214
1267
|
warnings = _coerce_string_list(detection.get("warnings"))
|
|
@@ -1308,13 +1361,7 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1308
1361
|
approvals_command = payload.get("approvals_command")
|
|
1309
1362
|
if blocked and dry_run:
|
|
1310
1363
|
review_command = (
|
|
1311
|
-
str(
|
|
1312
|
-
if approval_center_url and isinstance(approvals_command, str) and approvals_command
|
|
1313
|
-
else "hol-guard approvals"
|
|
1314
|
-
if approval_center_url
|
|
1315
|
-
else str(rerun_command)
|
|
1316
|
-
if isinstance(rerun_command, str) and rerun_command
|
|
1317
|
-
else f"hol-guard run {harness}"
|
|
1364
|
+
str(rerun_command) if isinstance(rerun_command, str) and rerun_command else f"hol-guard run {harness}"
|
|
1318
1365
|
)
|
|
1319
1366
|
inspect_command = (
|
|
1320
1367
|
str(diff_command) if isinstance(diff_command, str) and diff_command else f"hol-guard diff {harness}"
|
|
@@ -1324,12 +1371,29 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1324
1371
|
if isinstance(review_hint, str) and review_hint
|
|
1325
1372
|
else "Rerun without --dry-run to review the full blocker set and continue into the harness launch."
|
|
1326
1373
|
)
|
|
1327
|
-
|
|
1374
|
+
steps = [
|
|
1328
1375
|
{
|
|
1329
1376
|
"title": "Resolve the blocked launch",
|
|
1330
1377
|
"command": review_command,
|
|
1331
1378
|
"detail": review_detail,
|
|
1332
1379
|
},
|
|
1380
|
+
]
|
|
1381
|
+
if approval_center_url:
|
|
1382
|
+
approval_command = (
|
|
1383
|
+
str(approvals_command)
|
|
1384
|
+
if isinstance(approvals_command, str) and approvals_command
|
|
1385
|
+
else "hol-guard approvals"
|
|
1386
|
+
)
|
|
1387
|
+
steps.append(
|
|
1388
|
+
{
|
|
1389
|
+
"title": "Open the approvals queue",
|
|
1390
|
+
"command": approval_command,
|
|
1391
|
+
"detail": (
|
|
1392
|
+
"Review any queued approval requests after the prompt appears, then retry the guarded command."
|
|
1393
|
+
),
|
|
1394
|
+
}
|
|
1395
|
+
)
|
|
1396
|
+
steps.append(
|
|
1333
1397
|
{
|
|
1334
1398
|
"title": "Inspect only the changed config entries (optional)",
|
|
1335
1399
|
"command": inspect_command,
|
|
@@ -1338,17 +1402,19 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1338
1402
|
"Guard still needs you to review."
|
|
1339
1403
|
),
|
|
1340
1404
|
},
|
|
1341
|
-
]
|
|
1342
|
-
if blocked and isinstance(review_hint, str) and review_hint:
|
|
1343
|
-
command = (
|
|
1344
|
-
str(approvals_command)
|
|
1345
|
-
if approval_center_url and isinstance(approvals_command, str) and approvals_command
|
|
1346
|
-
else "hol-guard approvals"
|
|
1347
|
-
if approval_center_url
|
|
1348
|
-
else str(rerun_command)
|
|
1349
|
-
if isinstance(rerun_command, str) and rerun_command
|
|
1350
|
-
else f"hol-guard run {harness}"
|
|
1351
1405
|
)
|
|
1406
|
+
return steps
|
|
1407
|
+
if blocked and isinstance(review_hint, str) and review_hint:
|
|
1408
|
+
if approval_center_url:
|
|
1409
|
+
command = (
|
|
1410
|
+
str(approvals_command)
|
|
1411
|
+
if isinstance(approvals_command, str) and approvals_command
|
|
1412
|
+
else "hol-guard approvals"
|
|
1413
|
+
)
|
|
1414
|
+
elif isinstance(rerun_command, str) and rerun_command:
|
|
1415
|
+
command = str(rerun_command)
|
|
1416
|
+
else:
|
|
1417
|
+
command = f"hol-guard run {harness}"
|
|
1352
1418
|
return [{"title": "Resolve the blocked launch", "command": command, "detail": review_hint}]
|
|
1353
1419
|
if dry_run:
|
|
1354
1420
|
launch_command = (
|
|
@@ -1749,5 +1815,5 @@ _RENDERERS: dict[str, Any] = {
|
|
|
1749
1815
|
"protect": _render_protect,
|
|
1750
1816
|
"preflight": _render_preflight,
|
|
1751
1817
|
"scan": _render_scan,
|
|
1752
|
-
"explain":
|
|
1818
|
+
"explain": _render_explain,
|
|
1753
1819
|
}
|