plugin-scanner 2.0.116__tar.gz → 2.0.118__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.116 → plugin_scanner-2.0.118}/PKG-INFO +1 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/guard-api.test.ts +24 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/guard-api.ts +8 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/guard-types.ts +10 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/runtime-overview.tsx +32 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/pyproject.toml +1 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/pyproject.toml.bak +1 -1
- plugin_scanner-2.0.118/src/codex_plugin_scanner/guard/access_graph_events.py +223 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/approvals.py +99 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/commands.py +10 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/consumer/service.py +8 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +6 -6
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/edge_events.py +93 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/redaction.py +15 -1
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/detectors.py +79 -2
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +59 -9
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/runner.py +115 -4
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +32 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +25 -3
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/store.py +131 -24
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/version.py +1 -1
- plugin_scanner-2.0.118/tests/test_guard_cloud_local_sync.py +451 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_connect_flow.py +4 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_event_schema_v1.py +66 -2
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_launch_env.py +81 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_prompt_injection.py +80 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_risk.py +37 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime.py +33 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime_detectors.py +90 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_surface_server.py +64 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.dockerignore +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.gitignore +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/Dockerfile +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/data-flow-evidence-card.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/requirements.txt +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_data_flow.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/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.118
|
|
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
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
parseActionEnvelope,
|
|
5
5
|
parseDecisionV2
|
|
6
6
|
} from "./guard-api";
|
|
7
|
+
import { resolveCloudSyncHealthCopy } from "./runtime-overview";
|
|
7
8
|
import {
|
|
8
9
|
resolveDecisionV2Detail,
|
|
9
10
|
resolveDecisionV2Title,
|
|
@@ -29,6 +30,29 @@ assert(snapshot.cloud_pairing_state.dashboard_url === snapshot.dashboard_url, "d
|
|
|
29
30
|
assert(snapshot.cloud_pairing_state.inbox_url === snapshot.inbox_url, "demo inbox URL is preserved");
|
|
30
31
|
assert(snapshot.cloud_pairing_state.fleet_url === snapshot.fleet_url, "demo fleet URL is preserved");
|
|
31
32
|
assert(snapshot.cloud_pairing_state.connect_url === snapshot.connect_url, "demo connect URL is preserved");
|
|
33
|
+
assert(snapshot.cloud_sync_health.state === "pending", "demo snapshot exposes pending Cloud sync health");
|
|
34
|
+
|
|
35
|
+
const expectedSyncHealthLabels = {
|
|
36
|
+
healthy: "Cloud sync healthy",
|
|
37
|
+
pending: "Cloud sync pending",
|
|
38
|
+
failed: "Cloud sync needs attention",
|
|
39
|
+
degraded: "Cloud sync degraded",
|
|
40
|
+
disabled: "Cloud sync disabled",
|
|
41
|
+
stale: "Cloud sync stale"
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
for (const [state, label] of Object.entries(expectedSyncHealthLabels)) {
|
|
45
|
+
const copy = resolveCloudSyncHealthCopy({
|
|
46
|
+
state: state as keyof typeof expectedSyncHealthLabels,
|
|
47
|
+
label,
|
|
48
|
+
detail: `${label} detail`,
|
|
49
|
+
pending_events: state === "pending" ? 2 : 0,
|
|
50
|
+
last_synced_at: state === "disabled" ? null : "2026-04-24T00:00:00+00:00",
|
|
51
|
+
next_retry_after: state === "failed" ? "2026-04-24T00:02:00+00:00" : null
|
|
52
|
+
});
|
|
53
|
+
assert(copy.label === label, `T370: ${state} sync health label is preserved`);
|
|
54
|
+
assert(copy.detail.includes("detail"), `T370: ${state} sync health detail is preserved`);
|
|
55
|
+
}
|
|
32
56
|
|
|
33
57
|
const BASE_ENVELOPE: GuardActionEnvelope = {
|
|
34
58
|
schema_version: 1,
|
|
@@ -411,6 +411,14 @@ export function buildDemoRuntimeSnapshot(): GuardRuntimeSnapshot {
|
|
|
411
411
|
fleet_url: fleetUrl,
|
|
412
412
|
connect_url: connectUrl
|
|
413
413
|
},
|
|
414
|
+
cloud_sync_health: {
|
|
415
|
+
state: "pending",
|
|
416
|
+
label: "Cloud sync pending",
|
|
417
|
+
detail: "Waiting for the first shared Cloud proof from this machine.",
|
|
418
|
+
pending_events: 1,
|
|
419
|
+
last_synced_at: null,
|
|
420
|
+
next_retry_after: null
|
|
421
|
+
},
|
|
414
422
|
dashboard_url: dashboardUrl,
|
|
415
423
|
inbox_url: inboxUrl,
|
|
416
424
|
fleet_url: fleetUrl,
|
|
@@ -153,6 +153,15 @@ export type GuardCloudPairingState = {
|
|
|
153
153
|
connect_url: string;
|
|
154
154
|
};
|
|
155
155
|
|
|
156
|
+
export type GuardCloudSyncHealth = {
|
|
157
|
+
state: "healthy" | "pending" | "failed" | "degraded" | "disabled" | "stale";
|
|
158
|
+
label: string;
|
|
159
|
+
detail: string;
|
|
160
|
+
pending_events: number;
|
|
161
|
+
last_synced_at: string | null;
|
|
162
|
+
next_retry_after: string | null;
|
|
163
|
+
};
|
|
164
|
+
|
|
156
165
|
export type GuardRuntimeSnapshot = {
|
|
157
166
|
generated_at: string;
|
|
158
167
|
approval_center_url: string | null;
|
|
@@ -167,6 +176,7 @@ export type GuardRuntimeSnapshot = {
|
|
|
167
176
|
cloud_state_label: string;
|
|
168
177
|
cloud_state_detail: string;
|
|
169
178
|
cloud_pairing_state: GuardCloudPairingState;
|
|
179
|
+
cloud_sync_health: GuardCloudSyncHealth;
|
|
170
180
|
dashboard_url: string;
|
|
171
181
|
inbox_url: string;
|
|
172
182
|
fleet_url: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActionButton, Badge, KeyValueGrid, SectionLabel, Surface, Tag } from "./approval-center-primitives";
|
|
2
|
-
import type { GuardRuntimeSnapshot } from "./guard-types";
|
|
2
|
+
import type { GuardCloudSyncHealth, GuardRuntimeSnapshot } from "./guard-types";
|
|
3
3
|
|
|
4
4
|
type RuntimeOverviewProps = {
|
|
5
5
|
snapshot: GuardRuntimeSnapshot;
|
|
@@ -34,6 +34,35 @@ function remediationLine(snapshot: GuardRuntimeSnapshot): string {
|
|
|
34
34
|
return "Open Guard Cloud for shared proof, Watched Apps for local coverage, or the review queue when something needs your choice.";
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
export function resolveCloudSyncHealthCopy(health: GuardCloudSyncHealth): { label: string; detail: string } {
|
|
38
|
+
return {
|
|
39
|
+
label: health.label,
|
|
40
|
+
detail: health.detail
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function cloudSyncHealthTone(state: GuardCloudSyncHealth["state"]): "blue" | "slate" {
|
|
45
|
+
if (state === "disabled" || state === "failed" || state === "stale") {
|
|
46
|
+
return "slate";
|
|
47
|
+
}
|
|
48
|
+
return "blue";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function CloudSyncHealthCard(props: { health: GuardCloudSyncHealth }) {
|
|
52
|
+
const copy = resolveCloudSyncHealthCopy(props.health);
|
|
53
|
+
return (
|
|
54
|
+
<div className="rounded-xl border border-border bg-white px-5 py-4">
|
|
55
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
56
|
+
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-brand-blue">
|
|
57
|
+
Cloud sync health
|
|
58
|
+
</p>
|
|
59
|
+
<Tag tone={cloudSyncHealthTone(props.health.state)}>{copy.label}</Tag>
|
|
60
|
+
</div>
|
|
61
|
+
<p className="mt-2 text-sm leading-relaxed text-brand-dark/80">{copy.detail}</p>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
37
66
|
export function RuntimeOverview(props: RuntimeOverviewProps) {
|
|
38
67
|
const { snapshot } = props;
|
|
39
68
|
|
|
@@ -72,6 +101,8 @@ export function RuntimeOverview(props: RuntimeOverviewProps) {
|
|
|
72
101
|
/>
|
|
73
102
|
</div>
|
|
74
103
|
|
|
104
|
+
<CloudSyncHealthCard health={snapshot.cloud_sync_health} />
|
|
105
|
+
|
|
75
106
|
<div className="rounded-xl border border-border bg-white px-5 py-4">
|
|
76
107
|
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-brand-blue">
|
|
77
108
|
Recommended next step
|
|
@@ -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.118"
|
|
8
8
|
description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hol-guard"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.118"
|
|
8
8
|
description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Local access graph snapshot event queueing for Guard Cloud."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from .edge_events import build_access_graph_snapshot_event
|
|
9
|
+
from .models import HarnessDetection
|
|
10
|
+
from .redaction import redact_sensitive_text
|
|
11
|
+
from .store import GuardStore
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def queue_access_graph_snapshot(
|
|
15
|
+
*,
|
|
16
|
+
store: GuardStore,
|
|
17
|
+
detection: HarnessDetection,
|
|
18
|
+
artifacts: list[dict[str, object]],
|
|
19
|
+
now: str,
|
|
20
|
+
) -> None:
|
|
21
|
+
workspace_id = store.get_cloud_workspace_id()
|
|
22
|
+
device_id = store.get_or_create_installation_id()
|
|
23
|
+
device_fingerprint = f"device:{device_id}"
|
|
24
|
+
harness_fingerprint = f"harness:{detection.harness}"
|
|
25
|
+
agent_id = f"{detection.harness}:local-agent"
|
|
26
|
+
agent_fingerprint = f"agent:{agent_id}"
|
|
27
|
+
entities: list[dict[str, object]] = []
|
|
28
|
+
edges: list[dict[str, object]] = []
|
|
29
|
+
seen_fingerprints: set[str] = set()
|
|
30
|
+
|
|
31
|
+
def add_entity(entity: dict[str, object]) -> None:
|
|
32
|
+
fingerprint = entity.get("fingerprint")
|
|
33
|
+
if not isinstance(fingerprint, str) or fingerprint in seen_fingerprints:
|
|
34
|
+
return
|
|
35
|
+
seen_fingerprints.add(fingerprint)
|
|
36
|
+
entities.append(entity)
|
|
37
|
+
|
|
38
|
+
_add_device_harness_and_agent(
|
|
39
|
+
add_entity=add_entity,
|
|
40
|
+
edges=edges,
|
|
41
|
+
device_id=device_id,
|
|
42
|
+
device_fingerprint=device_fingerprint,
|
|
43
|
+
detection=detection,
|
|
44
|
+
harness_fingerprint=harness_fingerprint,
|
|
45
|
+
agent_id=agent_id,
|
|
46
|
+
agent_fingerprint=agent_fingerprint,
|
|
47
|
+
now=now,
|
|
48
|
+
)
|
|
49
|
+
_add_artifact_entities(
|
|
50
|
+
add_entity=add_entity,
|
|
51
|
+
edges=edges,
|
|
52
|
+
artifacts=artifacts,
|
|
53
|
+
agent_fingerprint=agent_fingerprint,
|
|
54
|
+
now=now,
|
|
55
|
+
)
|
|
56
|
+
snapshot_seed = {
|
|
57
|
+
"workspace": workspace_id,
|
|
58
|
+
"device": device_id,
|
|
59
|
+
"harness": detection.harness,
|
|
60
|
+
"generatedAt": now,
|
|
61
|
+
}
|
|
62
|
+
snapshot_hash = hashlib.sha256(json.dumps(snapshot_seed, sort_keys=True).encode("utf-8")).hexdigest()[:24]
|
|
63
|
+
snapshot_id = f"access-graph-{snapshot_hash}"
|
|
64
|
+
payload = {
|
|
65
|
+
"snapshotId": snapshot_id,
|
|
66
|
+
"generatedAt": now,
|
|
67
|
+
"entities": entities,
|
|
68
|
+
"edges": edges,
|
|
69
|
+
}
|
|
70
|
+
try:
|
|
71
|
+
store.add_guard_event_v1(
|
|
72
|
+
build_access_graph_snapshot_event(
|
|
73
|
+
snapshot_id=snapshot_id,
|
|
74
|
+
occurred_at=now,
|
|
75
|
+
payload=payload,
|
|
76
|
+
workspace_id=workspace_id,
|
|
77
|
+
device_id=device_id,
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
except Exception as error:
|
|
81
|
+
store.add_event(
|
|
82
|
+
"access_graph_snapshot_queue_failed",
|
|
83
|
+
{
|
|
84
|
+
"error_type": type(error).__name__,
|
|
85
|
+
"message": redact_sensitive_text(str(error)),
|
|
86
|
+
},
|
|
87
|
+
now,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _add_device_harness_and_agent(
|
|
92
|
+
*,
|
|
93
|
+
add_entity,
|
|
94
|
+
edges: list[dict[str, object]],
|
|
95
|
+
device_id: str,
|
|
96
|
+
device_fingerprint: str,
|
|
97
|
+
detection: HarnessDetection,
|
|
98
|
+
harness_fingerprint: str,
|
|
99
|
+
agent_id: str,
|
|
100
|
+
agent_fingerprint: str,
|
|
101
|
+
now: str,
|
|
102
|
+
) -> None:
|
|
103
|
+
add_entity(
|
|
104
|
+
{
|
|
105
|
+
"entityType": "device",
|
|
106
|
+
"entityId": device_id,
|
|
107
|
+
"displayName": "Local machine",
|
|
108
|
+
"fingerprint": device_fingerprint,
|
|
109
|
+
"metadata": {},
|
|
110
|
+
"firstSeenAt": now,
|
|
111
|
+
"lastSeenAt": now,
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
add_entity(
|
|
115
|
+
{
|
|
116
|
+
"entityType": "harness",
|
|
117
|
+
"entityId": detection.harness,
|
|
118
|
+
"displayName": detection.harness,
|
|
119
|
+
"fingerprint": harness_fingerprint,
|
|
120
|
+
"metadata": {"installed": detection.installed, "commandAvailable": detection.command_available},
|
|
121
|
+
"firstSeenAt": now,
|
|
122
|
+
"lastSeenAt": now,
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
edges.append(
|
|
126
|
+
{
|
|
127
|
+
"sourceFingerprint": device_fingerprint,
|
|
128
|
+
"targetFingerprint": harness_fingerprint,
|
|
129
|
+
"edgeType": "device_runs_harness",
|
|
130
|
+
"confidence": 100,
|
|
131
|
+
"metadata": {},
|
|
132
|
+
"firstSeenAt": now,
|
|
133
|
+
"lastSeenAt": now,
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
add_entity(
|
|
137
|
+
{
|
|
138
|
+
"entityType": "agent",
|
|
139
|
+
"entityId": agent_id,
|
|
140
|
+
"displayName": f"{detection.harness} local agent",
|
|
141
|
+
"fingerprint": agent_fingerprint,
|
|
142
|
+
"metadata": {"harness": detection.harness},
|
|
143
|
+
"firstSeenAt": now,
|
|
144
|
+
"lastSeenAt": now,
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
edges.append(
|
|
148
|
+
{
|
|
149
|
+
"sourceFingerprint": harness_fingerprint,
|
|
150
|
+
"targetFingerprint": agent_fingerprint,
|
|
151
|
+
"edgeType": "harness_runs_agent",
|
|
152
|
+
"confidence": 90,
|
|
153
|
+
"metadata": {},
|
|
154
|
+
"firstSeenAt": now,
|
|
155
|
+
"lastSeenAt": now,
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _add_artifact_entities(
|
|
161
|
+
*,
|
|
162
|
+
add_entity,
|
|
163
|
+
edges: list[dict[str, object]],
|
|
164
|
+
artifacts: list[dict[str, object]],
|
|
165
|
+
agent_fingerprint: str,
|
|
166
|
+
now: str,
|
|
167
|
+
) -> None:
|
|
168
|
+
for artifact in artifacts:
|
|
169
|
+
artifact_id = _non_empty_string(artifact.get("artifact_id"))
|
|
170
|
+
if artifact_id is None:
|
|
171
|
+
continue
|
|
172
|
+
artifact_type = _non_empty_string(artifact.get("artifact_type")) or "tool"
|
|
173
|
+
entity_type = _access_graph_entity_type(artifact_type)
|
|
174
|
+
fingerprint = f"{entity_type}:{artifact_id}"
|
|
175
|
+
add_entity(
|
|
176
|
+
{
|
|
177
|
+
"entityType": entity_type,
|
|
178
|
+
"entityId": artifact_id,
|
|
179
|
+
"displayName": _non_empty_string(artifact.get("artifact_name")) or artifact_id,
|
|
180
|
+
"fingerprint": fingerprint,
|
|
181
|
+
"metadata": {
|
|
182
|
+
"artifactType": artifact_type,
|
|
183
|
+
"sourceScope": _non_empty_string(artifact.get("source_scope")),
|
|
184
|
+
"policyAction": _non_empty_string(artifact.get("policy_action")),
|
|
185
|
+
"present": artifact.get("removed") is not True,
|
|
186
|
+
},
|
|
187
|
+
"firstSeenAt": now,
|
|
188
|
+
"lastSeenAt": now,
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
edge_type = _access_graph_artifact_edge_type(entity_type)
|
|
192
|
+
if edge_type is not None:
|
|
193
|
+
edges.append(
|
|
194
|
+
{
|
|
195
|
+
"sourceFingerprint": agent_fingerprint,
|
|
196
|
+
"targetFingerprint": fingerprint,
|
|
197
|
+
"edgeType": edge_type,
|
|
198
|
+
"confidence": 80,
|
|
199
|
+
"metadata": {},
|
|
200
|
+
"firstSeenAt": now,
|
|
201
|
+
"lastSeenAt": now,
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _access_graph_entity_type(artifact_type: str) -> str:
|
|
207
|
+
if artifact_type in {"skill", "mcp_server", "tool", "repository", "agent", "policy", "integration"}:
|
|
208
|
+
return artifact_type
|
|
209
|
+
return "tool"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _access_graph_artifact_edge_type(entity_type: str) -> str | None:
|
|
213
|
+
if entity_type == "skill":
|
|
214
|
+
return "agent_uses_skill"
|
|
215
|
+
if entity_type == "mcp_server":
|
|
216
|
+
return "agent_uses_mcp_server"
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _non_empty_string(value: object) -> str | None:
|
|
221
|
+
if isinstance(value, str) and value.strip():
|
|
222
|
+
return value
|
|
223
|
+
return None
|
{plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/approvals.py
RENAMED
|
@@ -6,7 +6,7 @@ import time
|
|
|
6
6
|
import uuid
|
|
7
7
|
from collections.abc import Mapping
|
|
8
8
|
from dataclasses import replace
|
|
9
|
-
from datetime import datetime, timezone
|
|
9
|
+
from datetime import datetime, timedelta, timezone
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
from urllib.parse import urlparse
|
|
12
12
|
|
|
@@ -374,11 +374,13 @@ def _build_runtime_cloud_context(store: GuardStore) -> dict[str, object]:
|
|
|
374
374
|
remote_payload_active=remote_payload_active,
|
|
375
375
|
)
|
|
376
376
|
dashboard_url, inbox_url, fleet_url, connect_url = _resolve_guard_urls(sync_url)
|
|
377
|
+
sync_health = _build_cloud_sync_health(store, credentials is not None, cloud_state)
|
|
377
378
|
return {
|
|
378
379
|
"sync_configured": credentials is not None,
|
|
379
380
|
"cloud_state": cloud_state,
|
|
380
381
|
"cloud_state_label": _runtime_cloud_state_label(cloud_state),
|
|
381
382
|
"cloud_state_detail": _runtime_cloud_state_detail(cloud_state),
|
|
383
|
+
"cloud_sync_health": sync_health,
|
|
382
384
|
"cloud_pairing_state": {
|
|
383
385
|
"state": cloud_state,
|
|
384
386
|
"label": _runtime_cloud_state_label(cloud_state),
|
|
@@ -396,6 +398,102 @@ def _build_runtime_cloud_context(store: GuardStore) -> dict[str, object]:
|
|
|
396
398
|
}
|
|
397
399
|
|
|
398
400
|
|
|
401
|
+
def _build_cloud_sync_health(store: GuardStore, sync_configured: bool, cloud_state: str) -> dict[str, object]:
|
|
402
|
+
pending_events = store.count_guard_events_v1(uploaded=False)
|
|
403
|
+
event_summary = store.get_sync_payload("guard_events_v1_summary") or {}
|
|
404
|
+
sync_summary = store.get_sync_payload("sync_summary") or {}
|
|
405
|
+
runtime_summary = store.get_sync_payload("runtime_session_summary") or {}
|
|
406
|
+
last_synced_at = _latest_sync_timestamp(
|
|
407
|
+
event_summary.get("synced_at"),
|
|
408
|
+
sync_summary.get("synced_at"),
|
|
409
|
+
runtime_summary.get("synced_at"),
|
|
410
|
+
)
|
|
411
|
+
if not sync_configured:
|
|
412
|
+
state = "disabled"
|
|
413
|
+
elif isinstance(event_summary, dict) and event_summary.get("status") == "failed":
|
|
414
|
+
state = "failed"
|
|
415
|
+
elif (
|
|
416
|
+
isinstance(event_summary, dict)
|
|
417
|
+
and event_summary.get("sync_skipped") is True
|
|
418
|
+
and event_summary.get("sync_reason") == "guard_events_endpoint_unavailable"
|
|
419
|
+
):
|
|
420
|
+
state = "degraded"
|
|
421
|
+
elif last_synced_at is not None and _timestamp_is_stale(last_synced_at):
|
|
422
|
+
state = "stale"
|
|
423
|
+
elif pending_events > 0 or cloud_state == "paired_waiting":
|
|
424
|
+
state = "pending"
|
|
425
|
+
else:
|
|
426
|
+
state = "healthy"
|
|
427
|
+
return {
|
|
428
|
+
"state": state,
|
|
429
|
+
"label": _cloud_sync_health_label(state),
|
|
430
|
+
"detail": _cloud_sync_health_detail(state, pending_events=pending_events),
|
|
431
|
+
"pending_events": pending_events,
|
|
432
|
+
"last_synced_at": last_synced_at,
|
|
433
|
+
"next_retry_after": event_summary.get("next_retry_after") if isinstance(event_summary, dict) else None,
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def _latest_sync_timestamp(*values: object) -> str | None:
|
|
438
|
+
parsed_values: list[tuple[datetime, str]] = []
|
|
439
|
+
for value in values:
|
|
440
|
+
if not isinstance(value, str) or not value.strip():
|
|
441
|
+
continue
|
|
442
|
+
parsed = _parse_timestamp(value)
|
|
443
|
+
if parsed is not None:
|
|
444
|
+
parsed_values.append((parsed, value))
|
|
445
|
+
if not parsed_values:
|
|
446
|
+
return None
|
|
447
|
+
return max(parsed_values, key=lambda item: item[0])[1]
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def _parse_timestamp(value: str) -> datetime | None:
|
|
451
|
+
try:
|
|
452
|
+
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
|
|
453
|
+
except ValueError:
|
|
454
|
+
return None
|
|
455
|
+
if parsed.tzinfo is None:
|
|
456
|
+
return parsed.replace(tzinfo=timezone.utc)
|
|
457
|
+
return parsed
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _timestamp_is_stale(value: str) -> bool:
|
|
461
|
+
parsed = _parse_timestamp(value)
|
|
462
|
+
if parsed is None:
|
|
463
|
+
return False
|
|
464
|
+
return datetime.now(timezone.utc) - parsed > timedelta(hours=24)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def _cloud_sync_health_label(state: str) -> str:
|
|
468
|
+
labels = {
|
|
469
|
+
"healthy": "Cloud sync healthy",
|
|
470
|
+
"pending": "Cloud sync pending",
|
|
471
|
+
"failed": "Cloud sync needs attention",
|
|
472
|
+
"degraded": "Cloud sync degraded",
|
|
473
|
+
"disabled": "Cloud sync disabled",
|
|
474
|
+
"stale": "Cloud sync stale",
|
|
475
|
+
}
|
|
476
|
+
return labels.get(state, "Cloud sync pending")
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def _cloud_sync_health_detail(state: str, *, pending_events: int) -> str:
|
|
480
|
+
if state == "healthy":
|
|
481
|
+
return "Guard Cloud has the latest local proof from this machine."
|
|
482
|
+
if state == "failed":
|
|
483
|
+
return "The latest Cloud upload failed. HOL Guard kept local protection active and will retry."
|
|
484
|
+
if state == "degraded":
|
|
485
|
+
return "Cloud accepted legacy sync, but v1 Guard event ingest is unavailable. Local protection stayed active."
|
|
486
|
+
if state == "disabled":
|
|
487
|
+
return "Local protection is active. Connect Cloud when you want shared team proof."
|
|
488
|
+
if state == "stale":
|
|
489
|
+
return "Cloud has not seen fresh local proof recently. Keep this runtime open or run sync again."
|
|
490
|
+
if pending_events == 1:
|
|
491
|
+
return "One local proof event is queued for the next Cloud sync."
|
|
492
|
+
if pending_events > 1:
|
|
493
|
+
return f"{pending_events} local proof events are queued for the next Cloud sync."
|
|
494
|
+
return "Waiting for the first shared Cloud proof from this machine."
|
|
495
|
+
|
|
496
|
+
|
|
399
497
|
def _resolve_runtime_cloud_state(*, sync_configured: bool, sync_completed: bool, remote_payload_active: bool) -> str:
|
|
400
498
|
if not sync_configured:
|
|
401
499
|
return "local_only"
|
{plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -95,6 +95,7 @@ from ..runtime.secret_file_requests import (
|
|
|
95
95
|
build_file_read_request_artifact,
|
|
96
96
|
build_tool_action_request_artifact,
|
|
97
97
|
extract_sensitive_file_read_request,
|
|
98
|
+
extract_sensitive_file_read_request_from_action,
|
|
98
99
|
extract_sensitive_tool_action_request,
|
|
99
100
|
is_explicitly_benign_tool_action_request,
|
|
100
101
|
)
|
|
@@ -1455,6 +1456,7 @@ def run_guard_command(
|
|
|
1455
1456
|
runtime_artifact = _hook_runtime_artifact(
|
|
1456
1457
|
harness=args.harness,
|
|
1457
1458
|
payload=payload,
|
|
1459
|
+
action_envelope=action_envelope,
|
|
1458
1460
|
home_dir=context.home_dir,
|
|
1459
1461
|
guard_home=context.guard_home,
|
|
1460
1462
|
workspace=runtime_workspace,
|
|
@@ -4019,6 +4021,7 @@ def _hook_runtime_artifact(
|
|
|
4019
4021
|
*,
|
|
4020
4022
|
harness: str,
|
|
4021
4023
|
payload: dict[str, object],
|
|
4024
|
+
action_envelope: GuardActionEnvelope | None,
|
|
4022
4025
|
home_dir: Path,
|
|
4023
4026
|
guard_home: Path,
|
|
4024
4027
|
workspace: Path | None,
|
|
@@ -4079,6 +4082,12 @@ def _hook_runtime_artifact(
|
|
|
4079
4082
|
cwd=workspace,
|
|
4080
4083
|
home_dir=home_dir,
|
|
4081
4084
|
)
|
|
4085
|
+
if request is None:
|
|
4086
|
+
request = (
|
|
4087
|
+
extract_sensitive_file_read_request_from_action(action_envelope, cwd=workspace, home_dir=home_dir)
|
|
4088
|
+
if action_envelope is not None
|
|
4089
|
+
else None
|
|
4090
|
+
)
|
|
4082
4091
|
source_scope = _coalesce_string(payload.get("source_scope"), "project")
|
|
4083
4092
|
config_path = str(_runtime_policy_path(harness, home_dir, workspace))
|
|
4084
4093
|
if request is not None:
|
|
@@ -5916,7 +5925,7 @@ def _guard_service_login_payload(
|
|
|
5916
5925
|
"client_title": label,
|
|
5917
5926
|
"client_version": _GUARD_CLIENT_VERSION,
|
|
5918
5927
|
}
|
|
5919
|
-
store.set_sync_credentials(sync_url, token, now)
|
|
5928
|
+
store.set_sync_credentials(sync_url, token, now, workspace_id=workspace or None)
|
|
5920
5929
|
store.set_sync_payload(_SERVICE_RUNTIME_PROFILE_STATE_KEY, service_profile, now)
|
|
5921
5930
|
device = store.set_device_label(label, now)
|
|
5922
5931
|
store.add_event(
|
{plugin_scanner-2.0.116 → plugin_scanner-2.0.118}/src/codex_plugin_scanner/guard/consumer/service.py
RENAMED
|
@@ -9,6 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
11
|
from ...models import ScanOptions
|
|
12
|
+
from ..access_graph_events import queue_access_graph_snapshot
|
|
12
13
|
from ..adapters import get_adapter, list_adapters
|
|
13
14
|
from ..adapters.base import HarnessContext
|
|
14
15
|
from ..capabilities import compute_capability_delta, normalize_artifact_capabilities, severity_from_deltas
|
|
@@ -658,6 +659,13 @@ def evaluate_detection(
|
|
|
658
659
|
},
|
|
659
660
|
now,
|
|
660
661
|
)
|
|
662
|
+
if persist:
|
|
663
|
+
queue_access_graph_snapshot(
|
|
664
|
+
store=store,
|
|
665
|
+
detection=detection,
|
|
666
|
+
artifacts=results,
|
|
667
|
+
now=now,
|
|
668
|
+
)
|
|
661
669
|
return {
|
|
662
670
|
"harness": detection.harness,
|
|
663
671
|
"artifacts": results,
|