plugin-scanner 2.0.136__tar.gz → 2.0.138__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.136 → plugin_scanner-2.0.138}/PKG-INFO +1 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/guard-api.ts +12 -0
- plugin_scanner-2.0.138/dashboard/src/runtime-overview.test.ts +107 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/runtime-overview.tsx +61 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/settings-workspace.test.ts +4 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/settings-workspace.tsx +29 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/get-started.md +33 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/pyproject.toml +5 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/pyproject.toml.bak +5 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/__init__.py +8 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/manager.py +30 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/server.py +7 -0
- plugin_scanner-2.0.138/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/version.py +1 -1
- plugin_scanner-2.0.138/tests/test_guard_daemon_repair_perf.py +226 -0
- plugin_scanner-2.0.136/dashboard/src/runtime-overview.test.ts +0 -55
- plugin_scanner-2.0.136/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.dockerignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.gitignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/approval-center-layout.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/approval-center-review-cards.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/data-flow-evidence-card.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/receipts-workspace.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/release-checklist.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/smoke-tests.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/requirements.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/action_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/runtime/threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/store_evidence.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/store_threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/benign-docs-fake-token.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/benign-health-endpoint.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/benign-nvmrc-fake-creds.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/benign-source-search.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/canary-exfil-encoded.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/canary-exfil.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/expected-decisions.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-dockerfile.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-encoded-shell-exfil.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-github-action.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-mcp-delete.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-mcp-secret-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-mcp-skill-exfil.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-npm-postinstall.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-prompt-env-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-prompt-guard-bypass.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-prompt-npmrc-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/malicious-python-setup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/guard-red-team/smoke-evidence-template.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_action_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_advisory_escalation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_approval_continuity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_approval_copy_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_approval_store_dedup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_approval_store_scale.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_canary_fixtures.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_cloud_local_sync.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_daemon_perf.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_data_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_decision_propagation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_evidence_store.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_harness_contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_mcp_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_policy_dedup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_prompt_injection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_red_team.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_resolution_copy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_safe_decode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_sandbox.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_skill_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_supply_chain.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_guard_web_recovery.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/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.138
|
|
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
|
|
@@ -631,3 +631,15 @@ export async function exportDiagnostics(): Promise<Blob> {
|
|
|
631
631
|
}
|
|
632
632
|
return response.blob();
|
|
633
633
|
}
|
|
634
|
+
|
|
635
|
+
export async function repairApprovalCenter(): Promise<{ repaired: boolean; cleared: string[] }> {
|
|
636
|
+
if (isGuardDemoMode()) {
|
|
637
|
+
return { repaired: true, cleared: ["locator", "daemon_state"] };
|
|
638
|
+
}
|
|
639
|
+
const response = await fetch(guardApiInput("/v1/daemon/repair"), withGuardAuth({ method: "POST" }));
|
|
640
|
+
if (!response.ok) {
|
|
641
|
+
throw new Error(`Repair failed with ${response.status}`);
|
|
642
|
+
}
|
|
643
|
+
return response.json() as Promise<{ repaired: boolean; cleared: string[] }>;
|
|
644
|
+
}
|
|
645
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { resolveCloudIntelCopy, resolveCloudSyncHealthCopy, resolveProtectionLevelCopy, resolveApprovalCenterHealth } from "./runtime-overview";
|
|
2
|
+
import type { GuardCloudSyncHealth, GuardRuntimeSnapshot } from "./guard-types";
|
|
3
|
+
|
|
4
|
+
function assert(condition: boolean, message: string): void {
|
|
5
|
+
if (!condition) {
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const healthDisabled: GuardCloudSyncHealth = {
|
|
11
|
+
state: "disabled",
|
|
12
|
+
label: "Sync disabled",
|
|
13
|
+
detail: "Cloud sync is turned off on this machine.",
|
|
14
|
+
pending_events: 0,
|
|
15
|
+
last_synced_at: null,
|
|
16
|
+
next_retry_after: null
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const healthHealthy: GuardCloudSyncHealth = {
|
|
20
|
+
state: "healthy",
|
|
21
|
+
label: "Sync healthy",
|
|
22
|
+
detail: "Cloud sync is running normally.",
|
|
23
|
+
pending_events: 0,
|
|
24
|
+
last_synced_at: new Date().toISOString(),
|
|
25
|
+
next_retry_after: null
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const localOnlyCopy = resolveCloudIntelCopy("local_only");
|
|
29
|
+
assert(localOnlyCopy.label === "Offline, free", "T507: local_only label should be 'Offline, free'");
|
|
30
|
+
assert(localOnlyCopy.detail.length > 0, "T507: local_only detail should not be empty");
|
|
31
|
+
assert(localOnlyCopy.detail.includes("locally"), "T507: local_only detail should mention 'locally'");
|
|
32
|
+
|
|
33
|
+
const localOnlySyncCopy = resolveCloudSyncHealthCopy(healthDisabled);
|
|
34
|
+
assert(localOnlySyncCopy.label === healthDisabled.label, "T507: cloud sync health label should match");
|
|
35
|
+
assert(localOnlySyncCopy.detail === healthDisabled.detail, "T507: cloud sync health detail should match");
|
|
36
|
+
|
|
37
|
+
const protectionBalanced = resolveProtectionLevelCopy("balanced");
|
|
38
|
+
assert(protectionBalanced.includes("secrets"), "T507: balanced description should mention secrets");
|
|
39
|
+
|
|
40
|
+
const pairedActiveCopy = resolveCloudIntelCopy("paired_active");
|
|
41
|
+
assert(pairedActiveCopy.label === "Synced, pro", "T508: paired_active label should be 'Synced, pro'");
|
|
42
|
+
assert(pairedActiveCopy.detail.length > 0, "T508: paired_active detail should not be empty");
|
|
43
|
+
assert(pairedActiveCopy.detail.includes("Guard Cloud"), "T508: paired_active detail should mention Guard Cloud");
|
|
44
|
+
|
|
45
|
+
const pairedWaitingCopy = resolveCloudIntelCopy("paired_waiting");
|
|
46
|
+
assert(pairedWaitingCopy.label === "Pairing…", "T508: paired_waiting label should be 'Pairing…'");
|
|
47
|
+
|
|
48
|
+
const pairedActiveSyncCopy = resolveCloudSyncHealthCopy(healthHealthy);
|
|
49
|
+
assert(pairedActiveSyncCopy.label === healthHealthy.label, "T508: healthy sync label should match");
|
|
50
|
+
|
|
51
|
+
const protectionStrict = resolveProtectionLevelCopy("strict");
|
|
52
|
+
assert(protectionStrict.includes("network"), "T508: strict description should mention network");
|
|
53
|
+
|
|
54
|
+
const protectionCustom = resolveProtectionLevelCopy("custom");
|
|
55
|
+
assert(protectionCustom.includes("Custom"), "T508: custom description should mention Custom");
|
|
56
|
+
|
|
57
|
+
const baseSnapshot: GuardRuntimeSnapshot = {
|
|
58
|
+
generated_at: new Date().toISOString(),
|
|
59
|
+
approval_center_url: "http://localhost:7392/approval",
|
|
60
|
+
runtime_state: {
|
|
61
|
+
session_id: "sess-1",
|
|
62
|
+
daemon_host: "localhost",
|
|
63
|
+
daemon_port: 7391,
|
|
64
|
+
started_at: new Date().toISOString(),
|
|
65
|
+
last_heartbeat_at: new Date().toISOString(),
|
|
66
|
+
approval_center_url: "http://localhost:7392/approval",
|
|
67
|
+
},
|
|
68
|
+
pending_count: 0,
|
|
69
|
+
receipt_count: 0,
|
|
70
|
+
headline_state: "protected",
|
|
71
|
+
headline_label: "Protected",
|
|
72
|
+
headline_detail: "Guard is active.",
|
|
73
|
+
sync_configured: false,
|
|
74
|
+
cloud_state: "local_only",
|
|
75
|
+
cloud_state_label: "Offline",
|
|
76
|
+
cloud_state_detail: "Running locally.",
|
|
77
|
+
cloud_pairing_state: { state: "local_only", label: "Offline", detail: "No cloud." },
|
|
78
|
+
cloud_sync_health: healthDisabled,
|
|
79
|
+
dashboard_url: "http://localhost:7392",
|
|
80
|
+
inbox_url: "http://localhost:7392/inbox",
|
|
81
|
+
fleet_url: "http://localhost:7392/fleet",
|
|
82
|
+
connect_url: "http://localhost:7392/connect",
|
|
83
|
+
items: [],
|
|
84
|
+
latest_receipts: [],
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const healthyApproval = resolveApprovalCenterHealth(baseSnapshot);
|
|
88
|
+
assert(healthyApproval.state === "ready", "T738: protected snapshot with URL should be ready");
|
|
89
|
+
assert(healthyApproval.label.toLowerCase().includes("ready"), "T738: ready label should say ready");
|
|
90
|
+
assert(healthyApproval.detail.includes("http://localhost:7392/approval"), "T738: ready detail should include the URL");
|
|
91
|
+
|
|
92
|
+
const nullRuntimeSnapshot: GuardRuntimeSnapshot = { ...baseSnapshot, runtime_state: null };
|
|
93
|
+
const offlineApproval = resolveApprovalCenterHealth(nullRuntimeSnapshot);
|
|
94
|
+
assert(offlineApproval.state === "stale", "T738: null runtime_state (non-setup) should be stale");
|
|
95
|
+
assert(offlineApproval.label.toLowerCase().includes("offline"), "T738: stale label should mention offline");
|
|
96
|
+
|
|
97
|
+
const setupSnapshot: GuardRuntimeSnapshot = { ...baseSnapshot, runtime_state: null, headline_state: "setup" };
|
|
98
|
+
const startingApproval = resolveApprovalCenterHealth(setupSnapshot);
|
|
99
|
+
assert(startingApproval.state === "starting", "T738: null runtime_state + setup headline should be starting");
|
|
100
|
+
assert(startingApproval.label.toLowerCase().includes("starting"), "T738: starting label should say starting");
|
|
101
|
+
|
|
102
|
+
const noUrlSnapshot: GuardRuntimeSnapshot = { ...baseSnapshot, approval_center_url: null };
|
|
103
|
+
const repairApproval = resolveApprovalCenterHealth(noUrlSnapshot);
|
|
104
|
+
assert(repairApproval.state === "repair_needed", "T738: null approval_center_url should need repair");
|
|
105
|
+
assert(repairApproval.label.toLowerCase().includes("unreachable"), "T738: repair label should mention unreachable");
|
|
106
|
+
assert(repairApproval.detail.toLowerCase().includes("repair"), "T738: repair detail should suggest repair action");
|
|
107
|
+
|
|
@@ -40,6 +40,44 @@ function remediationLine(snapshot: GuardRuntimeSnapshot): string {
|
|
|
40
40
|
return "Open Guard Cloud for shared proof, Watched Apps for local coverage, or the review queue when something needs your choice.";
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export type ApprovalCenterHealthState = "ready" | "starting" | "stale" | "repair_needed";
|
|
44
|
+
|
|
45
|
+
export type ApprovalCenterHealthCopy = {
|
|
46
|
+
state: ApprovalCenterHealthState;
|
|
47
|
+
label: string;
|
|
48
|
+
detail: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export function resolveApprovalCenterHealth(snapshot: GuardRuntimeSnapshot): ApprovalCenterHealthCopy {
|
|
52
|
+
if (snapshot.runtime_state === null) {
|
|
53
|
+
if (snapshot.headline_state === "setup") {
|
|
54
|
+
return {
|
|
55
|
+
state: "starting",
|
|
56
|
+
label: "Approval center starting",
|
|
57
|
+
detail: "Guard is setting up the local approval center. This takes a few seconds.",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
state: "stale",
|
|
62
|
+
label: "Approval center offline",
|
|
63
|
+
detail: "The local approval center is not running. Start Guard to restore the approval link.",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (snapshot.approval_center_url === null) {
|
|
67
|
+
return {
|
|
68
|
+
state: "repair_needed",
|
|
69
|
+
label: "Approval center unreachable",
|
|
70
|
+
detail: "The approval center URL is missing. Use the repair action in Settings to restore it.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
state: "ready",
|
|
75
|
+
label: "Approval center ready",
|
|
76
|
+
detail: `The approval center is running and accepting requests at ${snapshot.approval_center_url}.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
43
81
|
export function resolveCloudSyncHealthCopy(health: GuardCloudSyncHealth): { label: string; detail: string } {
|
|
44
82
|
return {
|
|
45
83
|
label: health.label,
|
|
@@ -95,6 +133,28 @@ function CloudSyncHealthCard(props: { health: GuardCloudSyncHealth }) {
|
|
|
95
133
|
);
|
|
96
134
|
}
|
|
97
135
|
|
|
136
|
+
function approvalHealthTone(state: ApprovalCenterHealthState): "green" | "blue" | "slate" | "red" {
|
|
137
|
+
if (state === "ready") return "green";
|
|
138
|
+
if (state === "starting") return "blue";
|
|
139
|
+
if (state === "repair_needed") return "red";
|
|
140
|
+
return "slate";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function ApprovalCenterHealthCard(props: { snapshot: GuardRuntimeSnapshot }) {
|
|
144
|
+
const copy = resolveApprovalCenterHealth(props.snapshot);
|
|
145
|
+
return (
|
|
146
|
+
<div className="rounded-xl border border-border bg-white px-5 py-4">
|
|
147
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
148
|
+
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-brand-blue">
|
|
149
|
+
Approval center health
|
|
150
|
+
</p>
|
|
151
|
+
<Tag tone={approvalHealthTone(copy.state)}>{copy.label}</Tag>
|
|
152
|
+
</div>
|
|
153
|
+
<p className="mt-2 text-sm leading-relaxed text-brand-dark/80">{copy.detail}</p>
|
|
154
|
+
</div>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
98
158
|
function WatchedAppsCard(props: { inventory: GuardInventoryItem[] | undefined }) {
|
|
99
159
|
const inventory = props.inventory ?? [];
|
|
100
160
|
return (
|
|
@@ -247,6 +307,7 @@ export function RuntimeOverview(props: RuntimeOverviewProps) {
|
|
|
247
307
|
</div>
|
|
248
308
|
|
|
249
309
|
<CloudSyncHealthCard health={snapshot.cloud_sync_health} />
|
|
310
|
+
<ApprovalCenterHealthCard snapshot={snapshot} />
|
|
250
311
|
|
|
251
312
|
<div className="rounded-xl border border-border bg-white px-5 py-4">
|
|
252
313
|
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-brand-blue">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveSecurityLevelDescription, buildClearPolicyPayload } from "./settings-workspace";
|
|
2
|
+
import { repairApprovalCenter } from "./guard-api";
|
|
2
3
|
|
|
3
4
|
function assert(condition: boolean, message: string): void {
|
|
4
5
|
if (!condition) {
|
|
@@ -25,3 +26,6 @@ assert(!("harness" in clearAllPayload) || clearAllPayload.harness === undefined,
|
|
|
25
26
|
|
|
26
27
|
const clearNonePayload = buildClearPolicyPayload(false);
|
|
27
28
|
assert(clearNonePayload.all === false, "T530: clearPolicy payload with all=false should have all=false");
|
|
29
|
+
|
|
30
|
+
assert(typeof repairApprovalCenter === "function", "T739: repairApprovalCenter should be exported as a function");
|
|
31
|
+
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
SectionLabel,
|
|
14
14
|
Tag
|
|
15
15
|
} from "./approval-center-primitives";
|
|
16
|
-
import { clearEvidence, exportDiagnostics, fetchSettings, updateSettings, clearPolicy } from "./guard-api";
|
|
16
|
+
import { clearEvidence, exportDiagnostics, fetchSettings, updateSettings, clearPolicy, repairApprovalCenter } from "./guard-api";
|
|
17
17
|
import { resolveProtectionLevelCopy } from "./runtime-overview";
|
|
18
18
|
import type { GuardSettings, GuardSettingsPayload } from "./guard-types";
|
|
19
19
|
|
|
@@ -163,6 +163,7 @@ export function SettingsWorkspace() {
|
|
|
163
163
|
const [clearingApprovals, setClearingApprovals] = useState(false);
|
|
164
164
|
const [clearingEvidence, setClearingEvidence] = useState(false);
|
|
165
165
|
const [exporting, setExporting] = useState(false);
|
|
166
|
+
const [repairing, setRepairing] = useState(false);
|
|
166
167
|
const [actionMessage, setActionMessage] = useState<string | null>(null);
|
|
167
168
|
const saveSuccessTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
168
169
|
|
|
@@ -359,6 +360,22 @@ export function SettingsWorkspace() {
|
|
|
359
360
|
}
|
|
360
361
|
}, []);
|
|
361
362
|
|
|
363
|
+
const handleRepairApprovalCenter = useCallback(async () => {
|
|
364
|
+
if (!window.confirm("Reset the approval center locator? The daemon will be reachable again after Guard restarts. Pending approvals are preserved.")) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
setRepairing(true);
|
|
368
|
+
setActionMessage(null);
|
|
369
|
+
try {
|
|
370
|
+
await repairApprovalCenter();
|
|
371
|
+
setActionMessage("Approval center repaired. Restart Guard to reconnect.");
|
|
372
|
+
} catch (error) {
|
|
373
|
+
setActionMessage(error instanceof Error ? error.message : "Unable to repair approval center.");
|
|
374
|
+
} finally {
|
|
375
|
+
setRepairing(false);
|
|
376
|
+
}
|
|
377
|
+
}, []);
|
|
378
|
+
|
|
362
379
|
if (state.kind === "loading") {
|
|
363
380
|
return (
|
|
364
381
|
<div className="space-y-4">
|
|
@@ -629,6 +646,17 @@ export function SettingsWorkspace() {
|
|
|
629
646
|
</ActionButton>
|
|
630
647
|
</div>
|
|
631
648
|
</div>
|
|
649
|
+
<div>
|
|
650
|
+
<p className="text-sm font-semibold text-brand-dark">Repair local approval center</p>
|
|
651
|
+
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
|
652
|
+
Resets the approval center locator when the approval link returns an API error. Pending approvals are preserved.
|
|
653
|
+
</p>
|
|
654
|
+
<div className="mt-2">
|
|
655
|
+
<ActionButton onClick={handleRepairApprovalCenter} disabled={repairing} variant="secondary">
|
|
656
|
+
{repairing ? "Repairing…" : "Repair approval center"}
|
|
657
|
+
</ActionButton>
|
|
658
|
+
</div>
|
|
659
|
+
</div>
|
|
632
660
|
{actionMessage ? (
|
|
633
661
|
<p className="guard-fade-in text-sm leading-6 text-brand-dark/70">{actionMessage}</p>
|
|
634
662
|
) : null}
|
|
@@ -270,3 +270,36 @@ That means the user should never get a silent pass-through on a risky Codex acti
|
|
|
270
270
|
- native Bash deny plus HOL Guard approval-center recovery for sensitive shell actions
|
|
271
271
|
- same-chat approve or deny when Codex can render the inline MCP prompt
|
|
272
272
|
- explicit approval-center recovery when the session cannot
|
|
273
|
+
|
|
274
|
+
## Seamless approvals
|
|
275
|
+
|
|
276
|
+
When Guard blocks a launch, it opens a persistent approval link in the terminal rather than pausing the session. You can resolve requests without leaving your harness:
|
|
277
|
+
|
|
278
|
+
1. Guard returns the approval URL in the block output and queues the request locally.
|
|
279
|
+
2. Open the approval center at the URL or in your browser.
|
|
280
|
+
3. Approve or deny the request from the approval center UI or the CLI:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
hol-guard approvals approve <request-id>
|
|
284
|
+
hol-guard approvals deny <request-id>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
4. After you resolve the request, Guard emits copy telling you to return to your AI assistant and retry. No page reload or session restart is needed.
|
|
288
|
+
|
|
289
|
+
To inspect a pending request's details or get the approval URL, pass the request-id to the `approve` command with `--dry-run`, or visit the approval center URL shown in the block message directly.
|
|
290
|
+
|
|
291
|
+
## Troubleshooting
|
|
292
|
+
|
|
293
|
+
### Approval link says API error
|
|
294
|
+
|
|
295
|
+
If the approval center URL in a block message returns an API error, the local approval center locator may be stale.
|
|
296
|
+
Use the **Repair approval center** action in the Guard dashboard Settings tab, or call the repair endpoint directly when the daemon is running. The port shown in Guard's status output or the dashboard URL is your daemon port:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
GUARD_PORT=$(hol-guard status --json 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print((d.get('runtime_state') or {}).get('daemon_port', d.get('daemon_port', 4781)))" 2>/dev/null || echo 4781)
|
|
300
|
+
curl -s -X POST "http://127.0.0.1:${GUARD_PORT}/v1/daemon/repair" \
|
|
301
|
+
-H "X-Guard-Token: $(cat ~/.hol-guard/daemon-auth-token)"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
After repair, restart Guard, then retry the block message URL or relaunch your harness through Guard. Pending approval requests are preserved across repairs.
|
|
305
|
+
|
|
@@ -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.138"
|
|
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"
|
|
@@ -98,3 +98,7 @@ select = ["E", "F", "W", "I", "N", "UP", "B", "A", "SIM", "RUF"]
|
|
|
98
98
|
[tool.pytest.ini_options]
|
|
99
99
|
testpaths = ["tests"]
|
|
100
100
|
python_files = ["test_*.py"]
|
|
101
|
+
addopts = ["-m", "not slow"]
|
|
102
|
+
markers = [
|
|
103
|
+
"slow: marks tests as slow (deselected by default; run with -m slow to include)",
|
|
104
|
+
]
|
|
@@ -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.138"
|
|
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"
|
|
@@ -100,3 +100,7 @@ select = ["E", "F", "W", "I", "N", "UP", "B", "A", "SIM", "RUF"]
|
|
|
100
100
|
[tool.pytest.ini_options]
|
|
101
101
|
testpaths = ["tests"]
|
|
102
102
|
python_files = ["test_*.py"]
|
|
103
|
+
addopts = ["-m", "not slow"]
|
|
104
|
+
markers = [
|
|
105
|
+
"slow: marks tests as slow (deselected by default; run with -m slow to include)",
|
|
106
|
+
]
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/__init__.py
RENAMED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from .manager import
|
|
5
|
+
from .manager import (
|
|
6
|
+
ensure_guard_daemon,
|
|
7
|
+
guard_daemon_url_for_home,
|
|
8
|
+
load_guard_daemon_auth_token,
|
|
9
|
+
load_guard_daemon_url,
|
|
10
|
+
repair_approval_center_locator,
|
|
11
|
+
)
|
|
6
12
|
|
|
7
13
|
__all__ = [
|
|
8
14
|
"GuardDaemonServer",
|
|
@@ -12,6 +18,7 @@ __all__ = [
|
|
|
12
18
|
"load_guard_daemon_auth_token",
|
|
13
19
|
"load_guard_daemon_url",
|
|
14
20
|
"load_guard_surface_daemon_client",
|
|
21
|
+
"repair_approval_center_locator",
|
|
15
22
|
]
|
|
16
23
|
|
|
17
24
|
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/manager.py
RENAMED
|
@@ -187,6 +187,36 @@ def clear_guard_daemon_state(guard_home: Path) -> None:
|
|
|
187
187
|
_write_private_text(state_path, "{}")
|
|
188
188
|
|
|
189
189
|
|
|
190
|
+
def repair_approval_center_locator(guard_home: Path) -> dict[str, object]:
|
|
191
|
+
"""Remove a stale approval center locator and optionally clear dead daemon state.
|
|
192
|
+
|
|
193
|
+
Only clears daemon-state.json when the recorded PID is no longer running,
|
|
194
|
+
so a live daemon's state is not disturbed. Raises OSError if a required
|
|
195
|
+
write fails so callers can detect incomplete repair.
|
|
196
|
+
|
|
197
|
+
Safe to call while the database is live. Returns a dict describing what was cleared.
|
|
198
|
+
"""
|
|
199
|
+
cleared: list[str] = []
|
|
200
|
+
locator = _locator_path(guard_home)
|
|
201
|
+
if locator.is_file():
|
|
202
|
+
locator.unlink()
|
|
203
|
+
cleared.append("locator")
|
|
204
|
+
state = _state_path(guard_home)
|
|
205
|
+
if state.is_file():
|
|
206
|
+
state_payload = _load_state(guard_home)
|
|
207
|
+
pid = state_payload.get("pid") if isinstance(state_payload, dict) else None
|
|
208
|
+
daemon_is_live = (
|
|
209
|
+
isinstance(pid, int)
|
|
210
|
+
and pid > 0
|
|
211
|
+
and _guard_daemon_pid_is_running(pid)
|
|
212
|
+
and _guard_daemon_pid_matches_command(pid, expected_guard_home=guard_home)
|
|
213
|
+
)
|
|
214
|
+
if not daemon_is_live:
|
|
215
|
+
_write_private_text(state, "{}")
|
|
216
|
+
cleared.append("daemon_state")
|
|
217
|
+
return {"repaired": True, "cleared": cleared}
|
|
218
|
+
|
|
219
|
+
|
|
190
220
|
def _locator_path(guard_home: Path) -> Path:
|
|
191
221
|
return guard_home / _APPROVAL_CENTER_LOCATOR_FILE
|
|
192
222
|
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.138}/src/codex_plugin_scanner/guard/daemon/server.py
RENAMED
|
@@ -38,6 +38,7 @@ from .manager import (
|
|
|
38
38
|
GUARD_DAEMON_COMPATIBILITY_VERSION,
|
|
39
39
|
clear_guard_daemon_state,
|
|
40
40
|
load_guard_daemon_auth_token,
|
|
41
|
+
repair_approval_center_locator,
|
|
41
42
|
write_guard_daemon_state,
|
|
42
43
|
)
|
|
43
44
|
|
|
@@ -401,6 +402,10 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
401
402
|
if parsed.path == "/v1/settings":
|
|
402
403
|
self._handle_settings_update(payload)
|
|
403
404
|
return
|
|
405
|
+
if parsed.path == "/v1/daemon/repair":
|
|
406
|
+
result = repair_approval_center_locator(self.server.store.guard_home) # type: ignore[attr-defined]
|
|
407
|
+
self._write_json(result)
|
|
408
|
+
return
|
|
404
409
|
request_id, action, matched = self._resolve_request_action(path_parts, payload)
|
|
405
410
|
if not matched:
|
|
406
411
|
self.send_response(404)
|
|
@@ -996,6 +1001,7 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
996
1001
|
if path in {
|
|
997
1002
|
"/v1/inventory",
|
|
998
1003
|
"/v1/connect/state",
|
|
1004
|
+
"/v1/daemon/repair",
|
|
999
1005
|
"/v1/evidence",
|
|
1000
1006
|
"/v1/evidence/export",
|
|
1001
1007
|
"/v1/policy",
|
|
@@ -1167,6 +1173,7 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
1167
1173
|
"/v1/policy/decisions",
|
|
1168
1174
|
"/v1/policy/clear",
|
|
1169
1175
|
"/v1/settings",
|
|
1176
|
+
"/v1/daemon/repair",
|
|
1170
1177
|
}:
|
|
1171
1178
|
return True
|
|
1172
1179
|
if len(path_parts) == 4 and path_parts[:2] == ["v1", "operations"] and path_parts[3] in {"items", "status"}:
|