plugin-scanner 2.0.102__tar.gz → 2.0.104__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.102 → plugin_scanner-2.0.104}/PKG-INFO +1 -1
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-layout.tsx +14 -18
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-utils.ts +30 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-api.test.ts +141 -3
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-api.ts +112 -4
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-types.ts +57 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/pyproject.toml +1 -1
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/commands.py +3 -4
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/config.py +22 -0
- plugin_scanner-2.0.104/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- plugin_scanner-2.0.104/src/codex_plugin_scanner/guard/runtime/detectors.py +148 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/runner.py +37 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_config_paths.py +21 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime.py +38 -0
- plugin_scanner-2.0.104/tests/test_guard_runtime_detectors.py +295 -0
- plugin_scanner-2.0.102/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.dockerignore +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.gitignore +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/Dockerfile +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/requirements.txt +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/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.104
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
2
|
-
|
|
3
|
-
|
|
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 {
|
|
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 {
|
|
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.
|
|
7
|
+
version = "2.0.104"
|
|
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.104"
|
|
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.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -1912,12 +1912,11 @@ def run_guard_command(
|
|
|
1912
1912
|
output_stream=output_stream,
|
|
1913
1913
|
)
|
|
1914
1914
|
return 0
|
|
1915
|
+
incoming_reason = _decision_v2_harness_message(payload) or payload.get("permission_decision_reason")
|
|
1915
1916
|
if _should_emit_native_hook_exit_block(args, event_name=hook_event_name, policy_action=policy_action):
|
|
1916
|
-
_emit_native_hook_block_stderr(
|
|
1917
|
-
_native_hook_reason_for_harness(args.harness, payload.get("permission_decision_reason"))
|
|
1918
|
-
)
|
|
1917
|
+
_emit_native_hook_block_stderr(_native_hook_reason_for_harness(args.harness, incoming_reason))
|
|
1919
1918
|
return 2
|
|
1920
|
-
reason = _native_hook_reason_for_harness(args.harness,
|
|
1919
|
+
reason = _native_hook_reason_for_harness(args.harness, incoming_reason)
|
|
1921
1920
|
if _should_emit_claude_native_pretooluse_notice(
|
|
1922
1921
|
args,
|
|
1923
1922
|
event_name=hook_event_name,
|
|
@@ -176,6 +176,9 @@ class GuardConfig:
|
|
|
176
176
|
telemetry: bool = False
|
|
177
177
|
sync: bool = False
|
|
178
178
|
billing: bool = False
|
|
179
|
+
runtime_detector_registry: bool = False
|
|
180
|
+
runtime_detector_timeout_ms: int = 50
|
|
181
|
+
runtime_detector_disabled_ids: tuple[str, ...] = ()
|
|
179
182
|
risk_actions: dict[str, GuardAction] | None = None
|
|
180
183
|
harness_risk_actions: dict[str, dict[str, GuardAction]] | None = None
|
|
181
184
|
harness_actions: dict[str, GuardAction] | None = None
|
|
@@ -252,6 +255,9 @@ def load_guard_config(guard_home: Path, workspace: Path | None = None) -> GuardC
|
|
|
252
255
|
telemetry=bool(merged.get("telemetry", False)),
|
|
253
256
|
sync=bool(merged.get("sync", False)),
|
|
254
257
|
billing=bool(merged.get("billing", False)),
|
|
258
|
+
runtime_detector_registry=_coerce_loaded_bool(merged.get("runtime_detector_registry", False)),
|
|
259
|
+
runtime_detector_timeout_ms=_coerce_loaded_positive_int(merged.get("runtime_detector_timeout_ms", 50), 50),
|
|
260
|
+
runtime_detector_disabled_ids=_coerce_loaded_string_tuple(merged.get("runtime_detector_disabled_ids")),
|
|
255
261
|
harness_actions=_coerce_action_map(merged.get("harnesses")),
|
|
256
262
|
publisher_actions=_coerce_action_map(merged.get("publishers")),
|
|
257
263
|
artifact_actions=_coerce_action_map(merged.get("artifacts")),
|
|
@@ -346,6 +352,22 @@ def _coerce_loaded_security_level(value: object) -> str:
|
|
|
346
352
|
return DEFAULT_SECURITY_LEVEL
|
|
347
353
|
|
|
348
354
|
|
|
355
|
+
def _coerce_loaded_bool(value: object) -> bool:
|
|
356
|
+
return value if isinstance(value, bool) else False
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _coerce_loaded_positive_int(value: object, fallback: int) -> int:
|
|
360
|
+
if isinstance(value, int) and not isinstance(value, bool) and value > 0:
|
|
361
|
+
return value
|
|
362
|
+
return fallback
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _coerce_loaded_string_tuple(value: object) -> tuple[str, ...]:
|
|
366
|
+
if not isinstance(value, list):
|
|
367
|
+
return ()
|
|
368
|
+
return tuple(item for item in value if isinstance(item, str) and item.strip())
|
|
369
|
+
|
|
370
|
+
|
|
349
371
|
def _coerce_risk_action_payload(value: object) -> dict[str, GuardAction]:
|
|
350
372
|
if not isinstance(value, dict):
|
|
351
373
|
raise ValueError("Risk actions must be a table.")
|