plugin-scanner 2.0.101__tar.gz → 2.0.103__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/PKG-INFO +1 -1
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-layout.tsx +14 -18
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-utils.ts +30 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-api.test.ts +141 -3
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-api.ts +112 -4
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-types.ts +57 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/pyproject.toml +1 -1
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/pyproject.toml.bak +1 -1
- plugin_scanner-2.0.103/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +88 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/hermes.py +13 -1
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw.py +13 -1
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/commands.py +3 -4
- plugin_scanner-2.0.103/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime.py +38 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_hermes_adapter.py +68 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_openclaw_adapter.py +68 -0
- plugin_scanner-2.0.101/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.dockerignore +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.gitignore +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/Dockerfile +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/requirements.txt +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.103
|
|
4
4
|
Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
6
6
|
Project-URL: Repository, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
@@ -35,7 +35,9 @@ import {
|
|
|
35
35
|
buildTechnicalSummary,
|
|
36
36
|
humanizeChangedFields,
|
|
37
37
|
harnessDisplayName,
|
|
38
|
-
|
|
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.103"
|
|
8
8
|
description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hol-guard"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.103"
|
|
8
8
|
description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Guard Cloud agent identity hints for local harness adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sqlite3
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from .base import HarnessContext
|
|
10
|
+
|
|
11
|
+
_SERVICE_RUNTIME_PROFILE_STATE_KEY = "service_runtime_profile"
|
|
12
|
+
_PROFILE_FIELDS = (
|
|
13
|
+
"runtime",
|
|
14
|
+
"label",
|
|
15
|
+
"workspace",
|
|
16
|
+
"surface",
|
|
17
|
+
"client_name",
|
|
18
|
+
"client_title",
|
|
19
|
+
"client_version",
|
|
20
|
+
"agent_id",
|
|
21
|
+
"principal_id",
|
|
22
|
+
)
|
|
23
|
+
_ENV_FIELDS = {
|
|
24
|
+
"runtime": "RUNTIME",
|
|
25
|
+
"label": "LABEL",
|
|
26
|
+
"workspace": "WORKSPACE",
|
|
27
|
+
"agent_id": "AGENT_ID",
|
|
28
|
+
"principal_id": "PRINCIPAL_ID",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def cloud_agent_identity_hints(
|
|
33
|
+
context: HarnessContext,
|
|
34
|
+
*,
|
|
35
|
+
runtime: str,
|
|
36
|
+
) -> dict[str, str] | None:
|
|
37
|
+
payload = _read_service_runtime_profile(context.guard_home / "guard.db")
|
|
38
|
+
if payload is None or _string_field(payload, "runtime") != runtime:
|
|
39
|
+
return None
|
|
40
|
+
hints = {field: value for field in _PROFILE_FIELDS if (value := _string_field(payload, field)) is not None}
|
|
41
|
+
return hints if hints else None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def cloud_agent_identity_environment(
|
|
45
|
+
identity: object,
|
|
46
|
+
*,
|
|
47
|
+
prefix: str,
|
|
48
|
+
) -> dict[str, str]:
|
|
49
|
+
if not isinstance(identity, dict):
|
|
50
|
+
return {}
|
|
51
|
+
env: dict[str, str] = {}
|
|
52
|
+
for field, suffix in _ENV_FIELDS.items():
|
|
53
|
+
value = identity.get(field)
|
|
54
|
+
if isinstance(value, str) and value:
|
|
55
|
+
env[f"{prefix}_GUARD_CLOUD_{suffix}"] = value
|
|
56
|
+
return env
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _read_service_runtime_profile(db_path: Path) -> dict[str, object] | None:
|
|
60
|
+
if not db_path.exists():
|
|
61
|
+
return None
|
|
62
|
+
try:
|
|
63
|
+
db_uri = f"{db_path.resolve().as_uri()}?mode=ro"
|
|
64
|
+
connection = sqlite3.connect(db_uri, uri=True)
|
|
65
|
+
try:
|
|
66
|
+
row = connection.execute(
|
|
67
|
+
"select payload_json from sync_state where state_key = ?",
|
|
68
|
+
(_SERVICE_RUNTIME_PROFILE_STATE_KEY,),
|
|
69
|
+
).fetchone()
|
|
70
|
+
finally:
|
|
71
|
+
connection.close()
|
|
72
|
+
except (OSError, sqlite3.Error):
|
|
73
|
+
return None
|
|
74
|
+
if row is None:
|
|
75
|
+
return None
|
|
76
|
+
try:
|
|
77
|
+
payload = json.loads(str(row[0]))
|
|
78
|
+
except json.JSONDecodeError:
|
|
79
|
+
return None
|
|
80
|
+
return payload if isinstance(payload, dict) else None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _string_field(payload: dict[str, object], field: str) -> str | None:
|
|
84
|
+
value = payload.get(field)
|
|
85
|
+
if not isinstance(value, str):
|
|
86
|
+
return None
|
|
87
|
+
stripped = value.strip()
|
|
88
|
+
return stripped or None
|
{plugin_scanner-2.0.101 → plugin_scanner-2.0.103}/src/codex_plugin_scanner/guard/adapters/hermes.py
RENAMED
|
@@ -16,6 +16,7 @@ from pathlib import Path
|
|
|
16
16
|
from ..models import GuardArtifact, HarnessDetection
|
|
17
17
|
from ..shims import install_guard_shim, remove_guard_shim
|
|
18
18
|
from .base import HarnessAdapter, HarnessContext, _command_available, _json_payload, _run_command_probe
|
|
19
|
+
from .cloud_identity import cloud_agent_identity_environment, cloud_agent_identity_hints
|
|
19
20
|
|
|
20
21
|
# Optional: PyYAML is preferred when available for robust YAML parsing.
|
|
21
22
|
# The adapter works without it via a line-based fallback parser.
|
|
@@ -83,6 +84,7 @@ class HermesHarnessAdapter(HarnessAdapter):
|
|
|
83
84
|
)
|
|
84
85
|
source_configs = _load_mcp_server_sources(context.home_dir / ".hermes")
|
|
85
86
|
overlay_servers = _overlay_servers(context=context, source_configs=source_configs)
|
|
87
|
+
cloud_identity = cloud_agent_identity_hints(context, runtime=self.harness)
|
|
86
88
|
overlay_path.write_text(json.dumps(overlay_servers, indent=2) + "\n", encoding="utf-8")
|
|
87
89
|
pretool_path.write_text(
|
|
88
90
|
json.dumps(_pretool_payload(context=context), indent=2) + "\n",
|
|
@@ -109,6 +111,8 @@ class HermesHarnessAdapter(HarnessAdapter):
|
|
|
109
111
|
*[str(note) for note in shim_manifest.get("notes", [])],
|
|
110
112
|
],
|
|
111
113
|
}
|
|
114
|
+
if cloud_identity is not None:
|
|
115
|
+
manifest["cloud_agent_identity"] = cloud_identity
|
|
112
116
|
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
|
113
117
|
return manifest
|
|
114
118
|
|
|
@@ -147,10 +151,17 @@ class HermesHarnessAdapter(HarnessAdapter):
|
|
|
147
151
|
pretool_path = manifest.get("pretool_hook_path")
|
|
148
152
|
if not isinstance(overlay_path, str) or not isinstance(pretool_path, str):
|
|
149
153
|
return {}
|
|
150
|
-
|
|
154
|
+
environment = {
|
|
151
155
|
"HERMES_GUARD_MCP_OVERLAY_PATH": overlay_path,
|
|
152
156
|
"HERMES_GUARD_PRETOOL_PATH": pretool_path,
|
|
153
157
|
}
|
|
158
|
+
environment.update(
|
|
159
|
+
cloud_agent_identity_environment(
|
|
160
|
+
cloud_agent_identity_hints(context, runtime=self.harness),
|
|
161
|
+
prefix="HERMES",
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
return environment
|
|
154
165
|
|
|
155
166
|
def runtime_probe(self, context: HarnessContext) -> dict[str, object] | None:
|
|
156
167
|
manifest = _json_payload(_managed_root(context) / "manifest.json")
|
|
@@ -165,6 +176,7 @@ class HermesHarnessAdapter(HarnessAdapter):
|
|
|
165
176
|
and isinstance(pretool_path, str)
|
|
166
177
|
and Path(pretool_path).exists()
|
|
167
178
|
),
|
|
179
|
+
"cloud_agent_identity_configured": bool(cloud_agent_identity_hints(context, runtime=self.harness)),
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
def approval_flow(self, *, managed_install: dict[str, object] | None = None) -> dict[str, object]:
|