plugin-scanner 2.0.126__tar.gz → 2.0.128__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.126 → plugin_scanner-2.0.128}/PKG-INFO +1 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/package.json +1 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/app.tsx +36 -0
- plugin_scanner-2.0.128/dashboard/src/approval-center-layout.test.ts +188 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/approval-center-layout.tsx +143 -31
- plugin_scanner-2.0.128/dashboard/src/approval-center-review-cards.tsx +144 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/approval-center-utils.ts +22 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/pyproject.toml +1 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/commands.py +54 -5
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/server.py +6 -4
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +1 -0
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +65 -0
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +164 -0
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/runtime/threat_intel.py +243 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/store.py +9 -0
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/store_threat_intel.py +209 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/version.py +1 -1
- plugin_scanner-2.0.128/tests/test_guard_advisory_escalation.py +123 -0
- plugin_scanner-2.0.128/tests/test_guard_threat_intel.py +581 -0
- plugin_scanner-2.0.126/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- plugin_scanner-2.0.126/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -1
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.dockerignore +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.gitignore +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/Dockerfile +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/data-flow-evidence-card.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/requirements.txt +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/store_evidence.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_approval_store_scale.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_cloud_local_sync.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_data_flow.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_evidence_store.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_mcp_protection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_prompt_injection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_safe_decode.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_sandbox.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_skill_protection.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_supply_chain.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.126 → plugin_scanner-2.0.128}/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.128
|
|
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
|
|
@@ -321,6 +321,42 @@ export function App() {
|
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
323
|
}}
|
|
324
|
+
onBulkApprove={async (ids) => {
|
|
325
|
+
const results = await Promise.allSettled(
|
|
326
|
+
ids.map((id) =>
|
|
327
|
+
resolveRequest({ requestId: id, action: "allow", scope: "once", reason: "" })
|
|
328
|
+
)
|
|
329
|
+
);
|
|
330
|
+
const succeeded = results.filter((r) => r.status === "fulfilled").length;
|
|
331
|
+
const failed = results.length - succeeded;
|
|
332
|
+
const label =
|
|
333
|
+
failed === 0
|
|
334
|
+
? `${succeeded} item${succeeded !== 1 ? "s" : ""} approved.`
|
|
335
|
+
: `${succeeded} approved, ${failed} failed. Retry the failed items manually.`;
|
|
336
|
+
setResolutionMessage(label);
|
|
337
|
+
navigate("/");
|
|
338
|
+
const [snapshotResult, receiptsResult, policiesResult] = await Promise.allSettled([fetchRuntimeSnapshot(), fetchReceipts(), fetchPolicies()]);
|
|
339
|
+
if (snapshotResult.status === "fulfilled") {
|
|
340
|
+
setRuntime({ kind: "ready", snapshot: snapshotResult.value });
|
|
341
|
+
setRequests({ kind: "ready", items: snapshotResult.value.items });
|
|
342
|
+
}
|
|
343
|
+
if (receiptsResult.status === "fulfilled") {
|
|
344
|
+
setReceipts({ kind: "ready", items: receiptsResult.value });
|
|
345
|
+
} else {
|
|
346
|
+
setReceipts({
|
|
347
|
+
kind: "error",
|
|
348
|
+
message: receiptsResult.reason instanceof Error ? receiptsResult.reason.message : "Unable to load local approval history."
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
if (policiesResult.status === "fulfilled") {
|
|
352
|
+
setPolicies({ kind: "ready", items: policiesResult.value });
|
|
353
|
+
} else {
|
|
354
|
+
setPolicies({
|
|
355
|
+
kind: "error",
|
|
356
|
+
message: policiesResult.reason instanceof Error ? policiesResult.reason.message : "Unable to load saved approvals."
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}}
|
|
324
360
|
fleetContent={
|
|
325
361
|
runtime.kind === "ready" ? (
|
|
326
362
|
<FleetWorkspace
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveEnvelopeDisplayText,
|
|
3
|
+
resolveStoppedCommandText,
|
|
4
|
+
resolveTerminalLabel,
|
|
5
|
+
displayArtifactName,
|
|
6
|
+
} from "./approval-center-utils";
|
|
7
|
+
import type { GuardActionEnvelope, GuardApprovalRequest } from "./guard-types";
|
|
8
|
+
|
|
9
|
+
function assert(condition: boolean, message: string): void {
|
|
10
|
+
if (!condition) {
|
|
11
|
+
throw new Error(message);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const BASE_ENVELOPE: GuardActionEnvelope = {
|
|
16
|
+
schema_version: 1,
|
|
17
|
+
action_id: "act-layout-test",
|
|
18
|
+
harness: "claude-code",
|
|
19
|
+
event_name: "tool_call",
|
|
20
|
+
action_type: "harness_start",
|
|
21
|
+
workspace: null,
|
|
22
|
+
workspace_hash: null,
|
|
23
|
+
tool_name: null,
|
|
24
|
+
command: null,
|
|
25
|
+
prompt_excerpt: null,
|
|
26
|
+
target_paths: [],
|
|
27
|
+
network_hosts: [],
|
|
28
|
+
mcp_server: null,
|
|
29
|
+
mcp_tool: null,
|
|
30
|
+
package_manager: null,
|
|
31
|
+
package_name: null,
|
|
32
|
+
script_name: null,
|
|
33
|
+
raw_payload_redacted: {}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const BASE_REQUEST: GuardApprovalRequest = {
|
|
37
|
+
request_id: "request-layout-test",
|
|
38
|
+
harness: "claude-code",
|
|
39
|
+
artifact_id: "claude-code:project:bash",
|
|
40
|
+
artifact_name: "bash",
|
|
41
|
+
artifact_type: "command",
|
|
42
|
+
artifact_hash: "sha256-layout",
|
|
43
|
+
publisher: null,
|
|
44
|
+
policy_action: "require-reapproval",
|
|
45
|
+
recommended_scope: "artifact",
|
|
46
|
+
changed_fields: ["first_seen"],
|
|
47
|
+
source_scope: "project",
|
|
48
|
+
config_path: "./claude.json",
|
|
49
|
+
launch_target: "git status",
|
|
50
|
+
transport: "stdio",
|
|
51
|
+
review_command: "hol-guard approvals approve request-layout-test",
|
|
52
|
+
approval_url: "http://127.0.0.1:4781/approvals/request-layout-test",
|
|
53
|
+
status: "pending",
|
|
54
|
+
resolution_action: null,
|
|
55
|
+
resolution_scope: null,
|
|
56
|
+
reason: null,
|
|
57
|
+
created_at: "2026-04-11T12:00:00Z",
|
|
58
|
+
resolved_at: null,
|
|
59
|
+
action_envelope_json: null
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const shellEnvelope: GuardActionEnvelope = {
|
|
63
|
+
...BASE_ENVELOPE,
|
|
64
|
+
action_type: "shell_command",
|
|
65
|
+
command: "git diff HEAD~1 -- src/"
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const shellRequest: GuardApprovalRequest = {
|
|
69
|
+
...BASE_REQUEST,
|
|
70
|
+
action_envelope_json: shellEnvelope
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
assert(
|
|
74
|
+
resolveStoppedCommandText(shellRequest).length > 0,
|
|
75
|
+
"T493: CTA section has non-empty command text for shell_command item (CTA content available above fold)"
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
assert(
|
|
79
|
+
resolveStoppedCommandText(shellRequest) === "git diff HEAD~1 -- src/",
|
|
80
|
+
"T494: resolveStoppedCommandText returns the envelope command for shell_command item"
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const longCommand = "a".repeat(200);
|
|
84
|
+
const longCommandEnvelope: GuardActionEnvelope = {
|
|
85
|
+
...BASE_ENVELOPE,
|
|
86
|
+
action_type: "shell_command",
|
|
87
|
+
command: longCommand
|
|
88
|
+
};
|
|
89
|
+
const longCommandRequest: GuardApprovalRequest = {
|
|
90
|
+
...BASE_REQUEST,
|
|
91
|
+
action_envelope_json: longCommandEnvelope
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
assert(
|
|
95
|
+
resolveStoppedCommandText(longCommandRequest) === longCommand,
|
|
96
|
+
"T495: resolveStoppedCommandText does not truncate a 200-character command string"
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
assert(
|
|
100
|
+
resolveStoppedCommandText(longCommandRequest).length === 200,
|
|
101
|
+
"T495: 200-char command preserved at full length"
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const harnessStartEnvelope: GuardActionEnvelope = { ...BASE_ENVELOPE, action_type: "harness_start" };
|
|
105
|
+
assert(
|
|
106
|
+
resolveEnvelopeDisplayText(harnessStartEnvelope) === null,
|
|
107
|
+
"T496: resolveEnvelopeDisplayText returns null for harness_start — no raw content displayed"
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
assert(
|
|
111
|
+
displayArtifactName(BASE_REQUEST) === "bash",
|
|
112
|
+
"T497: displayArtifactName returns artifact_name when present"
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const requestNoName: GuardApprovalRequest = {
|
|
116
|
+
...BASE_REQUEST,
|
|
117
|
+
artifact_name: "",
|
|
118
|
+
artifact_id: "claude-code:project:fallback-id"
|
|
119
|
+
};
|
|
120
|
+
assert(
|
|
121
|
+
displayArtifactName(requestNoName) === "claude-code:project:fallback-id",
|
|
122
|
+
"T497: displayArtifactName falls back to artifact_id when name is empty"
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const requestNoNameOrId: GuardApprovalRequest = {
|
|
126
|
+
...BASE_REQUEST,
|
|
127
|
+
artifact_name: "",
|
|
128
|
+
artifact_id: ""
|
|
129
|
+
};
|
|
130
|
+
assert(
|
|
131
|
+
displayArtifactName(requestNoNameOrId) === "this action",
|
|
132
|
+
"T497: displayArtifactName falls back to 'this action' when both name and id are empty"
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
assert(
|
|
136
|
+
resolveTerminalLabel(shellRequest) === "Command",
|
|
137
|
+
"T479: resolveTerminalLabel returns 'Command' for shell_command action type"
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const promptRequest: GuardApprovalRequest = {
|
|
141
|
+
...BASE_REQUEST,
|
|
142
|
+
action_envelope_json: { ...BASE_ENVELOPE, action_type: "prompt", prompt_excerpt: "Ignore instructions" }
|
|
143
|
+
};
|
|
144
|
+
assert(
|
|
145
|
+
resolveTerminalLabel(promptRequest) === "Prompt excerpt",
|
|
146
|
+
"T480: resolveTerminalLabel returns 'Prompt excerpt' for prompt action type"
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const fileReadRequest: GuardApprovalRequest = {
|
|
150
|
+
...BASE_REQUEST,
|
|
151
|
+
action_envelope_json: { ...BASE_ENVELOPE, action_type: "file_read", target_paths: ["/etc/hosts"] }
|
|
152
|
+
};
|
|
153
|
+
assert(
|
|
154
|
+
resolveTerminalLabel(fileReadRequest) === "File path",
|
|
155
|
+
"T481: resolveTerminalLabel returns 'File path' for file_read action type"
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const mcpRequest: GuardApprovalRequest = {
|
|
159
|
+
...BASE_REQUEST,
|
|
160
|
+
action_envelope_json: { ...BASE_ENVELOPE, action_type: "mcp_tool", mcp_server: "my-server", mcp_tool: "fetch" }
|
|
161
|
+
};
|
|
162
|
+
assert(
|
|
163
|
+
resolveTerminalLabel(mcpRequest) === "MCP server / tool",
|
|
164
|
+
"T482: resolveTerminalLabel returns 'MCP server / tool' for mcp_tool action type"
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const packageRequest: GuardApprovalRequest = {
|
|
168
|
+
...BASE_REQUEST,
|
|
169
|
+
action_envelope_json: { ...BASE_ENVELOPE, action_type: "package_script", package_manager: "npm", package_name: "lodash", script_name: null }
|
|
170
|
+
};
|
|
171
|
+
assert(
|
|
172
|
+
resolveTerminalLabel(packageRequest) === "Package",
|
|
173
|
+
"T483: resolveTerminalLabel returns 'Package' for package_script action type"
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const networkRequest: GuardApprovalRequest = {
|
|
177
|
+
...BASE_REQUEST,
|
|
178
|
+
action_envelope_json: { ...BASE_ENVELOPE, action_type: "network_request", network_hosts: ["api.example.com"] }
|
|
179
|
+
};
|
|
180
|
+
assert(
|
|
181
|
+
resolveTerminalLabel(networkRequest) === "Network destination",
|
|
182
|
+
"T484: resolveTerminalLabel returns 'Network destination' for network_request action type"
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
assert(
|
|
186
|
+
resolveTerminalLabel(BASE_REQUEST) === "Stopped command",
|
|
187
|
+
"T479-T484: resolveTerminalLabel returns 'Stopped command' when no envelope present"
|
|
188
|
+
);
|
|
@@ -38,8 +38,18 @@ import {
|
|
|
38
38
|
harnessDisplayName,
|
|
39
39
|
resolveDecisionV2Title,
|
|
40
40
|
resolveDecisionV2Detail,
|
|
41
|
-
resolveStoppedCommandText
|
|
41
|
+
resolveStoppedCommandText,
|
|
42
|
+
displayArtifactName,
|
|
43
|
+
resolveTerminalLabel,
|
|
44
|
+
scopeLabel
|
|
42
45
|
} from "./approval-center-utils";
|
|
46
|
+
import {
|
|
47
|
+
WhyThisPaused,
|
|
48
|
+
ApproveConsequence,
|
|
49
|
+
BlockConsequence,
|
|
50
|
+
KeyboardHints,
|
|
51
|
+
ConfirmModal
|
|
52
|
+
} from "./approval-center-review-cards";
|
|
43
53
|
import type {
|
|
44
54
|
GuardApprovalRequest,
|
|
45
55
|
GuardArtifactDiff,
|
|
@@ -94,6 +104,7 @@ type LayoutProps = {
|
|
|
94
104
|
workspace?: string;
|
|
95
105
|
reason: string;
|
|
96
106
|
}) => void;
|
|
107
|
+
onBulkApprove?: (ids: string[]) => void;
|
|
97
108
|
};
|
|
98
109
|
|
|
99
110
|
const scopeOptions: Array<{ value: DecisionScope; label: string; description: string }> = [
|
|
@@ -105,6 +116,7 @@ const scopeOptions: Array<{ value: DecisionScope; label: string; description: st
|
|
|
105
116
|
];
|
|
106
117
|
|
|
107
118
|
const commonScopeValues = new Set<DecisionScope>(["artifact", "workspace"]);
|
|
119
|
+
const broadScopeValues = new Set<DecisionScope>(["publisher", "harness", "global"]);
|
|
108
120
|
const queuePageSize = 8;
|
|
109
121
|
export function ApprovalCenterLayout(props: LayoutProps) {
|
|
110
122
|
const queuedItems = props.requests.kind === "ready" ? props.requests.items : [];
|
|
@@ -143,6 +155,7 @@ export function ApprovalCenterLayout(props: LayoutProps) {
|
|
|
143
155
|
onOpenRequest={props.onOpenRequest}
|
|
144
156
|
onGoHome={props.onGoHome}
|
|
145
157
|
onResolve={props.onResolve}
|
|
158
|
+
onBulkApprove={props.onBulkApprove}
|
|
146
159
|
/>
|
|
147
160
|
)}
|
|
148
161
|
</div>
|
|
@@ -182,6 +195,7 @@ function QueueWorkspace(props: {
|
|
|
182
195
|
onOpenRequest: (requestId: string) => void;
|
|
183
196
|
onGoHome: () => void;
|
|
184
197
|
onResolve: LayoutProps["onResolve"];
|
|
198
|
+
onBulkApprove?: (ids: string[]) => void;
|
|
185
199
|
}) {
|
|
186
200
|
if (props.requests.kind === "loading") {
|
|
187
201
|
return (
|
|
@@ -225,6 +239,7 @@ function QueueWorkspace(props: {
|
|
|
225
239
|
activeRequestId={props.activeRequestId}
|
|
226
240
|
items={props.requests.items}
|
|
227
241
|
onOpenRequest={props.onOpenRequest}
|
|
242
|
+
onBulkApprove={props.onBulkApprove}
|
|
228
243
|
/>
|
|
229
244
|
</div>
|
|
230
245
|
);
|
|
@@ -244,7 +259,7 @@ function QueueHeader(props: {
|
|
|
244
259
|
Review Queue
|
|
245
260
|
</h1>
|
|
246
261
|
<p className="max-w-2xl text-sm leading-relaxed text-muted-foreground">
|
|
247
|
-
HOL Guard paused
|
|
262
|
+
HOL Guard paused this before it ran. Review what was stopped, then approve or block it.
|
|
248
263
|
</p>
|
|
249
264
|
</div>
|
|
250
265
|
<div className="flex flex-wrap gap-2">
|
|
@@ -260,6 +275,7 @@ function QueueBrowser(props: {
|
|
|
260
275
|
activeRequestId: string | null;
|
|
261
276
|
items: GuardApprovalRequest[];
|
|
262
277
|
onOpenRequest: (requestId: string) => void;
|
|
278
|
+
onBulkApprove?: (ids: string[]) => void;
|
|
263
279
|
}) {
|
|
264
280
|
const [searchTerm, setSearchTerm] = useState("");
|
|
265
281
|
const [harnessFilter, setHarnessFilter] = useState("all");
|
|
@@ -311,8 +327,37 @@ function QueueBrowser(props: {
|
|
|
311
327
|
setPage((value) => Math.min(totalPages, value + 1));
|
|
312
328
|
}, [totalPages]);
|
|
313
329
|
|
|
330
|
+
const isReadOnlyItem = useCallback((item: GuardApprovalRequest) =>
|
|
331
|
+
item.policy_action !== "block" &&
|
|
332
|
+
(item.action_envelope_json?.action_type === "file_read" || item.artifact_type === "file_read_request"),
|
|
333
|
+
[]);
|
|
334
|
+
|
|
335
|
+
const bulkReadOnlyItems = useMemo(
|
|
336
|
+
() => filteredItems.filter(isReadOnlyItem),
|
|
337
|
+
[filteredItems, isReadOnlyItem]
|
|
338
|
+
);
|
|
339
|
+
const showBulkApprove =
|
|
340
|
+
props.onBulkApprove !== undefined &&
|
|
341
|
+
filteredItems.length > 0 &&
|
|
342
|
+
bulkReadOnlyItems.length === filteredItems.length;
|
|
343
|
+
|
|
344
|
+
const handleBulkApprove = useCallback(() => {
|
|
345
|
+
props.onBulkApprove?.(filteredItems.map((item) => item.request_id));
|
|
346
|
+
}, [props.onBulkApprove, filteredItems]);
|
|
347
|
+
|
|
314
348
|
return (
|
|
315
349
|
<section className="border-t border-slate-200/70 pt-6">
|
|
350
|
+
{showBulkApprove && (
|
|
351
|
+
<div className="mb-4">
|
|
352
|
+
<button
|
|
353
|
+
type="button"
|
|
354
|
+
onClick={handleBulkApprove}
|
|
355
|
+
className="rounded-full border border-brand-blue/30 bg-white px-4 py-2 text-sm font-medium text-brand-blue shadow-sm transition-colors hover:bg-brand-blue/5"
|
|
356
|
+
>
|
|
357
|
+
Approve all read-only actions ({filteredItems.length})
|
|
358
|
+
</button>
|
|
359
|
+
</div>
|
|
360
|
+
)}
|
|
316
361
|
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
|
317
362
|
<div>
|
|
318
363
|
<SectionLabel>Other waiting actions</SectionLabel>
|
|
@@ -424,6 +469,7 @@ function DecisionWorkspace(props: {
|
|
|
424
469
|
const [reason, setReason] = useState("approved in local approval center");
|
|
425
470
|
const [submitting, setSubmitting] = useState<"allow" | "block" | null>(null);
|
|
426
471
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
|
472
|
+
const [confirmPending, setConfirmPending] = useState<"allow" | "block" | null>(null);
|
|
427
473
|
|
|
428
474
|
useEffect(() => {
|
|
429
475
|
if (props.detail.kind === "ready") {
|
|
@@ -456,6 +502,57 @@ function DecisionWorkspace(props: {
|
|
|
456
502
|
[props.onResolve, readyRequestId, readyWorkspace, reason, scope]
|
|
457
503
|
);
|
|
458
504
|
|
|
505
|
+
const handleRequestResolve = useCallback(
|
|
506
|
+
(action: "allow" | "block") => {
|
|
507
|
+
if (broadScopeValues.has(scope)) {
|
|
508
|
+
setConfirmPending(action);
|
|
509
|
+
} else {
|
|
510
|
+
void handleResolve(action);
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
[scope, handleResolve]
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
const handleConfirmResolve = useCallback(() => {
|
|
517
|
+
if (confirmPending !== null) {
|
|
518
|
+
void handleResolve(confirmPending);
|
|
519
|
+
setConfirmPending(null);
|
|
520
|
+
}
|
|
521
|
+
}, [confirmPending, handleResolve]);
|
|
522
|
+
|
|
523
|
+
const handleCancelConfirm = useCallback(() => {
|
|
524
|
+
setConfirmPending(null);
|
|
525
|
+
}, []);
|
|
526
|
+
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
if (props.detail.kind !== "ready") return;
|
|
529
|
+
const onKeyDown = (event: KeyboardEvent) => {
|
|
530
|
+
if (submitting !== null) return;
|
|
531
|
+
if (confirmPending !== null) {
|
|
532
|
+
if (event.key === "Enter") {
|
|
533
|
+
handleConfirmResolve();
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (event.key === "Escape") {
|
|
537
|
+
handleCancelConfirm();
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
const target = event.target as HTMLElement;
|
|
543
|
+
if (
|
|
544
|
+
target.tagName === "INPUT" ||
|
|
545
|
+
target.tagName === "TEXTAREA" ||
|
|
546
|
+
target.tagName === "SELECT" ||
|
|
547
|
+
target.isContentEditable
|
|
548
|
+
) return;
|
|
549
|
+
if (event.key === "a" || event.key === "A") handleRequestResolve("allow");
|
|
550
|
+
else if (event.key === "b" || event.key === "B") handleRequestResolve("block");
|
|
551
|
+
};
|
|
552
|
+
window.addEventListener("keydown", onKeyDown);
|
|
553
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
554
|
+
}, [props.detail.kind, submitting, handleRequestResolve, confirmPending, handleConfirmResolve, handleCancelConfirm]);
|
|
555
|
+
|
|
459
556
|
if (props.detail.kind === "loading") {
|
|
460
557
|
return (
|
|
461
558
|
<div className="space-y-4">
|
|
@@ -481,6 +578,14 @@ function DecisionWorkspace(props: {
|
|
|
481
578
|
const broadScopeOpts = scopeOptions.filter((option) => !commonScopeValues.has(option.value));
|
|
482
579
|
return (
|
|
483
580
|
<div className="guard-surface-in space-y-4">
|
|
581
|
+
{confirmPending !== null && (
|
|
582
|
+
<ConfirmModal
|
|
583
|
+
action={confirmPending}
|
|
584
|
+
scopeLabel={scopeLabel(scope)}
|
|
585
|
+
onConfirm={handleConfirmResolve}
|
|
586
|
+
onCancel={handleCancelConfirm}
|
|
587
|
+
/>
|
|
588
|
+
)}
|
|
484
589
|
<RuleBuilder
|
|
485
590
|
item={item}
|
|
486
591
|
scope={scope}
|
|
@@ -491,7 +596,7 @@ function DecisionWorkspace(props: {
|
|
|
491
596
|
broadScopeOptions={broadScopeOpts}
|
|
492
597
|
onScopeChange={setScope}
|
|
493
598
|
onReasonChange={setReason}
|
|
494
|
-
onResolve={
|
|
599
|
+
onResolve={handleRequestResolve}
|
|
495
600
|
/>
|
|
496
601
|
<WhatChanged item={item} diff={diff} receipt={receipt} policy={policy} />
|
|
497
602
|
</div>
|
|
@@ -547,11 +652,9 @@ function WhatChanged(props: { item: GuardApprovalRequest; diff: GuardArtifactDif
|
|
|
547
652
|
<summary className="flex cursor-pointer select-none items-center justify-between gap-3 text-sm font-medium text-brand-dark [&::-webkit-details-marker]:hidden">
|
|
548
653
|
<span className="flex items-center gap-2">
|
|
549
654
|
<span className="text-brand-blue transition-transform duration-200 group-open:rotate-90">›</span>
|
|
550
|
-
|
|
551
|
-
</span>
|
|
552
|
-
<span className="hidden rounded-full bg-surface-1 px-3 py-1 font-mono text-[11px] text-muted-foreground sm:inline">
|
|
553
|
-
saved details
|
|
655
|
+
Technical details
|
|
554
656
|
</span>
|
|
657
|
+
<Badge tone="warning">{artifactTypeLabel(item.artifact_type)}</Badge>
|
|
555
658
|
</summary>
|
|
556
659
|
<div className="mt-4 space-y-3 border-l-2 border-brand-blue/10 pl-4">
|
|
557
660
|
<p className="text-sm leading-relaxed text-brand-dark/70">{buildStoppedReason(item, receipt)}</p>
|
|
@@ -591,37 +694,45 @@ function RuleBuilder(props: {
|
|
|
591
694
|
}) {
|
|
592
695
|
const previewText = getRulePreviewText(props.item, props.scope);
|
|
593
696
|
const allowLabel = props.scope === "artifact" ? "Approve once" : "Approve and remember";
|
|
697
|
+
const retryInstruction = props.item.decision_v2_json?.retry_instruction ?? null;
|
|
698
|
+
|
|
699
|
+
const handleAllow = useCallback(() => props.onResolve("allow"), [props.onResolve]);
|
|
700
|
+
const handleBlock = useCallback(() => props.onResolve("block"), [props.onResolve]);
|
|
701
|
+
|
|
594
702
|
return (
|
|
595
703
|
<section className="guard-surface-in relative overflow-hidden rounded-[2rem] border border-brand-blue/15 bg-[radial-gradient(circle_at_top_left,rgba(85,153,254,0.12),transparent_32%),linear-gradient(135deg,#ffffff_0%,#ffffff_58%,rgba(85,153,254,0.08)_100%)] p-5 shadow-[0_20px_60px_rgba(63,65,116,0.08)] sm:p-6 lg:p-7">
|
|
596
704
|
<div className="pointer-events-none absolute right-8 top-8 h-24 w-24 rounded-full bg-brand-green/20 blur-3xl" />
|
|
597
|
-
<div className="relative
|
|
598
|
-
<div>
|
|
599
|
-
<
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
<PolicyBadge action={props.item.policy_action} />
|
|
603
|
-
</div>
|
|
604
|
-
<div className="mt-4 max-w-3xl">
|
|
605
|
-
<SectionLabel>Needs your decision</SectionLabel>
|
|
606
|
-
<h3 className="mt-2 text-2xl font-semibold tracking-tight text-brand-dark sm:text-3xl">
|
|
607
|
-
{buildDecisionTitle(props.item)}
|
|
608
|
-
</h3>
|
|
609
|
-
<p className="mt-3 max-w-2xl text-sm leading-6 text-brand-dark/70">
|
|
610
|
-
{buildPauseLine(props.item)}
|
|
611
|
-
</p>
|
|
612
|
-
</div>
|
|
705
|
+
<div className="relative">
|
|
706
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
707
|
+
<Tag tone="blue">HOL Guard</Tag>
|
|
708
|
+
<Tag tone="slate">{harnessDisplayName(props.item.harness)}</Tag>
|
|
709
|
+
<PolicyBadge action={props.item.policy_action} />
|
|
613
710
|
</div>
|
|
711
|
+
<div className="mt-4 max-w-3xl">
|
|
712
|
+
<SectionLabel>Needs your decision</SectionLabel>
|
|
713
|
+
<h3 className="mt-2 text-2xl font-semibold tracking-tight text-brand-dark sm:text-3xl">
|
|
714
|
+
{buildDecisionTitle(props.item)}
|
|
715
|
+
</h3>
|
|
716
|
+
<p className="mt-3 max-w-2xl text-sm leading-6 text-brand-dark/70">
|
|
717
|
+
{buildPauseLine(props.item)}
|
|
718
|
+
</p>
|
|
719
|
+
</div>
|
|
720
|
+
</div>
|
|
721
|
+
|
|
722
|
+
<div className="relative mt-5">
|
|
614
723
|
<DecisionActionPanel
|
|
615
724
|
allowLabel={allowLabel}
|
|
616
725
|
previewText={previewText}
|
|
617
726
|
submitting={props.submitting}
|
|
618
727
|
isBlocked={props.item.policy_action === "block"}
|
|
619
|
-
|
|
620
|
-
|
|
728
|
+
retryInstruction={retryInstruction}
|
|
729
|
+
onAllow={handleAllow}
|
|
730
|
+
onBlock={handleBlock}
|
|
621
731
|
/>
|
|
622
732
|
</div>
|
|
623
733
|
|
|
624
734
|
<DecisionSteps activeStep={props.submitting === null ? 1 : 3} />
|
|
735
|
+
<KeyboardHints />
|
|
625
736
|
|
|
626
737
|
<div className="relative mt-6 grid gap-6 xl:grid-cols-[minmax(0,1.08fr)_minmax(340px,0.92fr)] xl:items-start">
|
|
627
738
|
<BlockedActionCard item={props.item} />
|
|
@@ -699,6 +810,7 @@ function DecisionActionPanel(props: {
|
|
|
699
810
|
previewText: string;
|
|
700
811
|
submitting: "allow" | "block" | null;
|
|
701
812
|
isBlocked: boolean;
|
|
813
|
+
retryInstruction: string | null;
|
|
702
814
|
onAllow: () => void;
|
|
703
815
|
onBlock: () => void;
|
|
704
816
|
}) {
|
|
@@ -708,6 +820,10 @@ function DecisionActionPanel(props: {
|
|
|
708
820
|
<p className="mt-2 text-sm leading-6 text-brand-dark/70">
|
|
709
821
|
{props.previewText}
|
|
710
822
|
</p>
|
|
823
|
+
<div className="mt-3 grid gap-1.5">
|
|
824
|
+
<ApproveConsequence retryInstruction={props.retryInstruction} />
|
|
825
|
+
<BlockConsequence />
|
|
826
|
+
</div>
|
|
711
827
|
<div className="mt-4 grid gap-2">
|
|
712
828
|
<ActionButton variant="success" onClick={props.onAllow} disabled={props.submitting !== null}>
|
|
713
829
|
{props.submitting === "allow" ? "Saving…" : (props.isBlocked ? "Allow — override block" : props.allowLabel)}
|
|
@@ -817,7 +933,6 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
|
|
|
817
933
|
<div className="p-4">
|
|
818
934
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
819
935
|
<SectionLabel>What was stopped</SectionLabel>
|
|
820
|
-
<Badge tone="warning">{artifactTypeLabel(props.item.artifact_type)}</Badge>
|
|
821
936
|
</div>
|
|
822
937
|
<h4 className="mt-2 text-xl font-semibold tracking-tight text-brand-dark">
|
|
823
938
|
{actionDisplayTitle(props.item)}
|
|
@@ -836,7 +951,7 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
|
|
|
836
951
|
<span className="h-2.5 w-2.5 rounded-full bg-brand-blue" />
|
|
837
952
|
<span className="h-2.5 w-2.5 rounded-full bg-brand-green" />
|
|
838
953
|
<span className="ml-2 font-mono text-[10px] uppercase tracking-[0.22em] text-white/45">
|
|
839
|
-
|
|
954
|
+
{resolveTerminalLabel(props.item)}
|
|
840
955
|
</span>
|
|
841
956
|
<span className="ml-auto">
|
|
842
957
|
<CopyCommandButton command={launchText} />
|
|
@@ -846,6 +961,7 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
|
|
|
846
961
|
{launchText}
|
|
847
962
|
</pre>
|
|
848
963
|
</div>
|
|
964
|
+
<WhyThisPaused item={props.item} />
|
|
849
965
|
{isBlocked && (
|
|
850
966
|
<div className="mt-3 rounded-[1rem] border border-brand-purple/20 bg-brand-purple/[0.05] px-3 py-2.5">
|
|
851
967
|
<p className="text-sm leading-6 text-brand-purple">
|
|
@@ -937,10 +1053,6 @@ function PolicyBadge(props: { action: string }) {
|
|
|
937
1053
|
return <Badge tone={tone}>{policyActionLabel(props.action)}</Badge>;
|
|
938
1054
|
}
|
|
939
1055
|
|
|
940
|
-
function displayArtifactName(item: GuardApprovalRequest): string {
|
|
941
|
-
return item.artifact_name || item.artifact_id || "this action";
|
|
942
|
-
}
|
|
943
|
-
|
|
944
1056
|
function simplifyRiskHeadline(headline: string, harness: string): string {
|
|
945
1057
|
const lowerHeadline = headline.toLowerCase();
|
|
946
1058
|
if (lowerHeadline.includes("sensitive native tool action") || lowerHeadline.includes("destructive shell command")) {
|