plugin-scanner 2.0.136__tar.gz → 2.0.137__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.137}/PKG-INFO +1 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/get-started.md +33 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/pyproject.toml +5 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/pyproject.toml.bak +5 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/__init__.py +8 -1
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/manager.py +30 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/server.py +7 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/version.py +1 -1
- plugin_scanner-2.0.137/tests/test_guard_daemon_repair_perf.py +226 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.dockerignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.gitignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-layout.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-review-cards.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/data-flow-evidence-card.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/receipts-workspace.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/runtime-overview.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/settings-workspace.test.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/release-checklist.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/smoke-tests.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/requirements.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/action_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/runtime/threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/store_evidence.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/store_threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/benign-docs-fake-token.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/benign-health-endpoint.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/benign-nvmrc-fake-creds.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/benign-source-search.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/canary-exfil-encoded.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/canary-exfil.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/expected-decisions.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-dockerfile.txt +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-encoded-shell-exfil.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-github-action.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-mcp-delete.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-mcp-secret-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-mcp-skill-exfil.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-npm-postinstall.js +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-prompt-env-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-prompt-guard-bypass.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-prompt-npmrc-read.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/malicious-python-setup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/guard-red-team/smoke-evidence-template.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_action_identity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_advisory_escalation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_approval_continuity.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_approval_copy_commands.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_approval_store_dedup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_approval_store_scale.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_canary_fixtures.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_cloud_local_sync.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_daemon_perf.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_data_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_decision_propagation.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_evidence_store.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_harness_contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_mcp_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_policy_dedup.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_prompt_injection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_red_team.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_resolution_copy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_safe_decode.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_sandbox.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_skill_protection.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_supply_chain.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_threat_intel.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_guard_web_recovery.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/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.137
|
|
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
|
|
@@ -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.137"
|
|
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.137"
|
|
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.137}/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.137}/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.137}/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"}:
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""Tests for T740-T745: daemon repair, performance, docs smoke, and red-team smoke."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sqlite3
|
|
6
|
+
import time
|
|
7
|
+
import uuid
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from codex_plugin_scanner.guard.daemon import repair_approval_center_locator
|
|
12
|
+
from codex_plugin_scanner.guard.models import GuardApprovalRequest
|
|
13
|
+
from codex_plugin_scanner.guard.store import GuardStore
|
|
14
|
+
from codex_plugin_scanner.guard.store_approvals import (
|
|
15
|
+
add_approval_request,
|
|
16
|
+
approval_index_statements,
|
|
17
|
+
approval_schema_statement,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _make_conn() -> sqlite3.Connection:
|
|
22
|
+
conn = sqlite3.connect(":memory:")
|
|
23
|
+
conn.row_factory = sqlite3.Row
|
|
24
|
+
conn.execute("pragma journal_mode=wal")
|
|
25
|
+
conn.execute(approval_schema_statement())
|
|
26
|
+
for stmt in approval_index_statements():
|
|
27
|
+
conn.execute(stmt)
|
|
28
|
+
return conn
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _make_request(
|
|
32
|
+
*,
|
|
33
|
+
harness: str = "codex",
|
|
34
|
+
artifact_id: str | None = None,
|
|
35
|
+
workspace: str | None = "ws-a",
|
|
36
|
+
launch_target: str | None = "run tool",
|
|
37
|
+
) -> GuardApprovalRequest:
|
|
38
|
+
rid = str(uuid.uuid4())
|
|
39
|
+
aid = artifact_id or f"codex:project:tool-{uuid.uuid4().hex[:8]}"
|
|
40
|
+
return GuardApprovalRequest(
|
|
41
|
+
request_id=rid,
|
|
42
|
+
harness=harness,
|
|
43
|
+
artifact_id=aid,
|
|
44
|
+
artifact_name="tool",
|
|
45
|
+
artifact_hash="hash-abc",
|
|
46
|
+
policy_action="require-reapproval",
|
|
47
|
+
recommended_scope="artifact",
|
|
48
|
+
changed_fields=("tool_action_request",),
|
|
49
|
+
source_scope="project",
|
|
50
|
+
config_path="/tmp/config.toml",
|
|
51
|
+
workspace=workspace,
|
|
52
|
+
launch_target=launch_target,
|
|
53
|
+
review_command=f"hol-guard approvals approve {rid}",
|
|
54
|
+
approval_url=f"http://127.0.0.1:5474/approvals/{rid}",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TestDaemonRepairPreservesPendingApprovals:
|
|
59
|
+
"""T740: stale locator repair does not lose pending approvals."""
|
|
60
|
+
|
|
61
|
+
def test_repair_clears_locator_but_preserves_store(self, tmp_path) -> None:
|
|
62
|
+
guard_home = tmp_path / "guard-home"
|
|
63
|
+
store = GuardStore(guard_home)
|
|
64
|
+
|
|
65
|
+
req = _make_request()
|
|
66
|
+
store.add_approval_request(req, "2026-01-01T00:00:00Z")
|
|
67
|
+
|
|
68
|
+
locator_path = guard_home / "approval-center-locator.json"
|
|
69
|
+
locator_path.parent.mkdir(parents=True, exist_ok=True)
|
|
70
|
+
locator_path.write_text('{"pid": 9999999, "daemon_url": "http://127.0.0.1:9999"}', encoding="utf-8")
|
|
71
|
+
|
|
72
|
+
result = repair_approval_center_locator(guard_home)
|
|
73
|
+
|
|
74
|
+
assert result["repaired"] is True
|
|
75
|
+
assert not locator_path.exists(), "Stale locator must be removed after repair"
|
|
76
|
+
pending = store.list_approval_requests()
|
|
77
|
+
assert len(pending) == 1, f"Pending approval must be preserved after repair, got {len(pending)}"
|
|
78
|
+
assert pending[0]["request_id"] == req.request_id
|
|
79
|
+
|
|
80
|
+
def test_repair_without_locator_is_idempotent(self, tmp_path) -> None:
|
|
81
|
+
guard_home = tmp_path / "guard-home"
|
|
82
|
+
store = GuardStore(guard_home)
|
|
83
|
+
store.add_approval_request(_make_request(), "2026-01-01T00:00:00Z")
|
|
84
|
+
|
|
85
|
+
result = repair_approval_center_locator(guard_home)
|
|
86
|
+
|
|
87
|
+
assert result["repaired"] is True
|
|
88
|
+
assert len(store.list_approval_requests()) == 1
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class TestNormalizedIdentityLookupPerformance:
|
|
92
|
+
"""T741: approval lookup by normalized identity stays under 50 ms with 100k approvals."""
|
|
93
|
+
|
|
94
|
+
@pytest.mark.slow
|
|
95
|
+
def test_lookup_by_identity_key_under_50ms_with_100k_rows(self) -> None:
|
|
96
|
+
from codex_plugin_scanner.guard.store_approvals import _normalized_identity_key # type: ignore[attr-defined]
|
|
97
|
+
|
|
98
|
+
conn = _make_conn()
|
|
99
|
+
harness = "codex"
|
|
100
|
+
artifact_id = "codex:project:perf-tool"
|
|
101
|
+
workspace = "ws-perf"
|
|
102
|
+
launch_target = "run perf-tool"
|
|
103
|
+
now = "2026-01-01T00:00:00Z"
|
|
104
|
+
|
|
105
|
+
for _ in range(100_000):
|
|
106
|
+
req = _make_request(
|
|
107
|
+
harness=harness,
|
|
108
|
+
artifact_id=f"codex:project:tool-{uuid.uuid4().hex[:8]}",
|
|
109
|
+
workspace=workspace,
|
|
110
|
+
)
|
|
111
|
+
add_approval_request(conn, req, now)
|
|
112
|
+
|
|
113
|
+
target = _make_request(
|
|
114
|
+
harness=harness, artifact_id=artifact_id, workspace=workspace, launch_target=launch_target
|
|
115
|
+
)
|
|
116
|
+
add_approval_request(conn, target, now)
|
|
117
|
+
identity_key = _normalized_identity_key(launch_target)
|
|
118
|
+
|
|
119
|
+
start = time.monotonic()
|
|
120
|
+
result = conn.execute(
|
|
121
|
+
"""
|
|
122
|
+
select request_id from approval_requests
|
|
123
|
+
where harness = ?
|
|
124
|
+
and artifact_id = ?
|
|
125
|
+
and workspace IS ?
|
|
126
|
+
and normalized_identity_key = ?
|
|
127
|
+
and status = 'pending'
|
|
128
|
+
order by created_at desc
|
|
129
|
+
limit 1
|
|
130
|
+
""",
|
|
131
|
+
(harness, artifact_id, workspace, identity_key),
|
|
132
|
+
).fetchone()
|
|
133
|
+
elapsed_ms = (time.monotonic() - start) * 1000
|
|
134
|
+
|
|
135
|
+
assert result is not None, "Target row must be found by identity key"
|
|
136
|
+
assert elapsed_ms < 50, f"Identity-key lookup took {elapsed_ms:.1f}ms, expected < 50ms"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class TestDuplicatePendingCollapsePerformance:
|
|
140
|
+
"""T742: duplicate pending collapse stays under 100 ms with 100k approvals."""
|
|
141
|
+
|
|
142
|
+
@pytest.mark.slow
|
|
143
|
+
def test_dedup_insert_under_100ms_with_100k_rows(self) -> None:
|
|
144
|
+
conn = _make_conn()
|
|
145
|
+
harness = "codex"
|
|
146
|
+
artifact_id = "codex:project:dedup-tool"
|
|
147
|
+
workspace = "ws-dedup"
|
|
148
|
+
launch_target = "run dedup-tool --flag"
|
|
149
|
+
now = "2026-01-01T00:00:00Z"
|
|
150
|
+
|
|
151
|
+
for _ in range(99_999):
|
|
152
|
+
req = _make_request(
|
|
153
|
+
harness=harness,
|
|
154
|
+
artifact_id=f"codex:project:tool-{uuid.uuid4().hex[:8]}",
|
|
155
|
+
workspace=workspace,
|
|
156
|
+
)
|
|
157
|
+
add_approval_request(conn, req, now)
|
|
158
|
+
|
|
159
|
+
first = _make_request(
|
|
160
|
+
harness=harness,
|
|
161
|
+
artifact_id=artifact_id,
|
|
162
|
+
workspace=workspace,
|
|
163
|
+
launch_target=launch_target,
|
|
164
|
+
)
|
|
165
|
+
first_id = add_approval_request(conn, first, now)
|
|
166
|
+
|
|
167
|
+
repeat = _make_request(
|
|
168
|
+
harness=harness, artifact_id=artifact_id, workspace=workspace, launch_target=launch_target
|
|
169
|
+
)
|
|
170
|
+
start = time.monotonic()
|
|
171
|
+
second_id = add_approval_request(conn, repeat, now)
|
|
172
|
+
elapsed_ms = (time.monotonic() - start) * 1000
|
|
173
|
+
|
|
174
|
+
assert first_id == second_id, "Duplicate must be collapsed"
|
|
175
|
+
assert elapsed_ms < 100, f"Dedup insert took {elapsed_ms:.1f}ms, expected < 100ms"
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class TestApproveOnceNoSecondPrompt:
|
|
179
|
+
"""T745: approve a canary once → retry immediately → no second prompt unless command changes."""
|
|
180
|
+
|
|
181
|
+
def test_approved_canary_policy_resolves_to_allow(self, tmp_path) -> None:
|
|
182
|
+
"""After approving a canary artifact, policy lookup must return 'allow' immediately."""
|
|
183
|
+
from codex_plugin_scanner.guard.models import PolicyDecision
|
|
184
|
+
from codex_plugin_scanner.guard.store import GuardStore
|
|
185
|
+
|
|
186
|
+
guard_home = tmp_path / "guard-home"
|
|
187
|
+
store = GuardStore(guard_home)
|
|
188
|
+
artifact_id = "codex:project:canary-tool"
|
|
189
|
+
artifact_hash_val = "hash-canary-v1"
|
|
190
|
+
|
|
191
|
+
store.upsert_policy(
|
|
192
|
+
PolicyDecision(
|
|
193
|
+
harness="codex",
|
|
194
|
+
scope="artifact",
|
|
195
|
+
action="allow",
|
|
196
|
+
artifact_id=artifact_id,
|
|
197
|
+
artifact_hash=artifact_hash_val,
|
|
198
|
+
),
|
|
199
|
+
"2026-01-01T00:00:00Z",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
result = store.resolve_policy("codex", artifact_id, artifact_hash_val, workspace=None)
|
|
203
|
+
assert result == "allow", f"Canary must resolve to 'allow' immediately after approval, got {result!r}"
|
|
204
|
+
|
|
205
|
+
def test_changed_artifact_hash_reprompts(self, tmp_path) -> None:
|
|
206
|
+
"""Canary with a different hash (changed command) must not inherit prior approval."""
|
|
207
|
+
from codex_plugin_scanner.guard.models import PolicyDecision
|
|
208
|
+
from codex_plugin_scanner.guard.store import GuardStore
|
|
209
|
+
|
|
210
|
+
guard_home = tmp_path / "guard-home"
|
|
211
|
+
store = GuardStore(guard_home)
|
|
212
|
+
artifact_id = "codex:project:canary-tool"
|
|
213
|
+
|
|
214
|
+
store.upsert_policy(
|
|
215
|
+
PolicyDecision(
|
|
216
|
+
harness="codex",
|
|
217
|
+
scope="artifact",
|
|
218
|
+
action="allow",
|
|
219
|
+
artifact_id=artifact_id,
|
|
220
|
+
artifact_hash="hash-canary-v1",
|
|
221
|
+
),
|
|
222
|
+
"2026-01-01T00:00:00Z",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
result = store.resolve_policy("codex", artifact_id, "hash-canary-v2-changed", workspace=None)
|
|
226
|
+
assert result is None, f"Changed hash must not inherit prior approval, got {result!r}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/.github/ISSUE_TEMPLATE/feature-request.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-layout.test.ts
RENAMED
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-primitives.tsx
RENAMED
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/dashboard/src/approval-center-review-cards.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/argparse_utils.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/__init__.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/best_practices.py
RENAMED
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/code_quality.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/manifest.py
RENAMED
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/marketplace.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/mcp_security.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/opencode.py
RENAMED
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.136 → plugin_scanner-2.0.137}/src/codex_plugin_scanner/checks/security.py
RENAMED
|
File without changes
|