plugin-scanner 2.0.128__tar.gz → 2.0.129__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.128 → plugin_scanner-2.0.129}/PKG-INFO +1 -1
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/package.json +1 -1
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/app.tsx +19 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/approval-center-layout.tsx +3 -1
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/guard-api.ts +21 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/guard-types.ts +1 -0
- plugin_scanner-2.0.129/dashboard/src/receipts-workspace.test.ts +58 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/receipts-workspace.tsx +77 -35
- plugin_scanner-2.0.129/dashboard/src/runtime-overview.test.ts +55 -0
- plugin_scanner-2.0.129/dashboard/src/runtime-overview.tsx +274 -0
- plugin_scanner-2.0.129/dashboard/src/settings-workspace.test.ts +27 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/settings-workspace.tsx +145 -15
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/harness-support.md +17 -0
- plugin_scanner-2.0.129/docs/guard/release-checklist.md +65 -0
- plugin_scanner-2.0.129/docs/guard/smoke-tests.md +132 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/pyproject.toml +1 -1
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/pyproject.toml.bak +1 -1
- plugin_scanner-2.0.129/src/codex_plugin_scanner/guard/adapters/contracts.py +203 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/commands.py +24 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/render.py +21 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/server.py +61 -7
- plugin_scanner-2.0.129/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- plugin_scanner-2.0.129/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +1 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/store_evidence.py +6 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/version.py +1 -1
- plugin_scanner-2.0.129/tests/fixtures/guard-red-team/README.md +27 -0
- plugin_scanner-2.0.129/tests/fixtures/guard-red-team/canary-exfil-encoded.py +22 -0
- plugin_scanner-2.0.129/tests/fixtures/guard-red-team/canary-exfil.py +25 -0
- plugin_scanner-2.0.129/tests/fixtures/guard-red-team/smoke-evidence-template.json +206 -0
- plugin_scanner-2.0.129/tests/test_guard_canary_fixtures.py +107 -0
- plugin_scanner-2.0.129/tests/test_guard_harness_contracts.py +179 -0
- plugin_scanner-2.0.128/dashboard/src/runtime-overview.tsx +0 -129
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- plugin_scanner-2.0.128/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -1
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.dockerignore +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.gitignore +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/Dockerfile +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/approval-center-layout.test.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/approval-center-review-cards.tsx +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/data-flow-evidence-card.tsx +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/requirements.txt +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/runtime/threat_intel.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/store_threat_intel.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_advisory_escalation.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_approval_store_scale.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_cloud_local_sync.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_data_flow.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_evidence_store.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_mcp_protection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_prompt_injection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_safe_decode.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_sandbox.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_skill_protection.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_supply_chain.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_threat_intel.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.128 → plugin_scanner-2.0.129}/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.129
|
|
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
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "vite build",
|
|
8
|
-
"test": "tsx src/guard-api.test.ts && tsx src/approval-center-layout.test.ts"
|
|
8
|
+
"test": "tsx src/guard-api.test.ts && tsx src/approval-center-layout.test.ts && tsx src/runtime-overview.test.ts && tsx src/receipts-workspace.test.ts && tsx src/settings-workspace.test.ts"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"react": "^19.2.0",
|
|
@@ -178,6 +178,24 @@ export function App() {
|
|
|
178
178
|
};
|
|
179
179
|
}, []);
|
|
180
180
|
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
let cancelled = false;
|
|
183
|
+
fetchInventory()
|
|
184
|
+
.then((items) => {
|
|
185
|
+
if (!cancelled) {
|
|
186
|
+
setInventory({ kind: "ready", items });
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
.catch(() => {
|
|
190
|
+
if (!cancelled) {
|
|
191
|
+
setInventory({ kind: "ready", items: [] });
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return () => {
|
|
195
|
+
cancelled = true;
|
|
196
|
+
};
|
|
197
|
+
}, []);
|
|
198
|
+
|
|
181
199
|
useEffect(() => {
|
|
182
200
|
let cancelled = false;
|
|
183
201
|
Promise.allSettled([fetchReceipts(), fetchPolicies()])
|
|
@@ -259,6 +277,7 @@ export function App() {
|
|
|
259
277
|
detail={detail}
|
|
260
278
|
receipts={receipts}
|
|
261
279
|
runtime={runtime}
|
|
280
|
+
inventory={inventory.kind === "ready" ? inventory.items : []}
|
|
262
281
|
activeRequestId={activeRequestId}
|
|
263
282
|
resolutionMessage={resolutionMessage}
|
|
264
283
|
homeContent={
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import type {
|
|
54
54
|
GuardApprovalRequest,
|
|
55
55
|
GuardArtifactDiff,
|
|
56
|
+
GuardInventoryItem,
|
|
56
57
|
GuardPolicyDecision,
|
|
57
58
|
GuardReceipt,
|
|
58
59
|
GuardRuntimeSnapshot,
|
|
@@ -89,6 +90,7 @@ type LayoutProps = {
|
|
|
89
90
|
detail: DetailState;
|
|
90
91
|
receipts: ReceiptsState;
|
|
91
92
|
runtime: RuntimeState;
|
|
93
|
+
inventory: GuardInventoryItem[];
|
|
92
94
|
activeRequestId: string | null;
|
|
93
95
|
resolutionMessage: string | null;
|
|
94
96
|
homeContent: ReactNode;
|
|
@@ -183,7 +185,7 @@ function RuntimeBanner(props: { runtime: RuntimeState }) {
|
|
|
183
185
|
</Surface>
|
|
184
186
|
);
|
|
185
187
|
}
|
|
186
|
-
return <RuntimeOverview snapshot={props.runtime.snapshot} />;
|
|
188
|
+
return <RuntimeOverview snapshot={props.runtime.snapshot} inventory={props.inventory} />;
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
function QueueWorkspace(props: {
|
|
@@ -610,3 +610,24 @@ export async function resolveRequest(input: {
|
|
|
610
610
|
})
|
|
611
611
|
});
|
|
612
612
|
}
|
|
613
|
+
|
|
614
|
+
export async function clearEvidence(): Promise<void> {
|
|
615
|
+
if (isGuardDemoMode()) {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const response = await fetch(guardApiInput("/v1/evidence"), withGuardAuth({ method: "DELETE" }));
|
|
619
|
+
if (!response.ok) {
|
|
620
|
+
throw new Error(`Clear evidence failed with ${response.status}`);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
export async function exportDiagnostics(): Promise<Blob> {
|
|
625
|
+
if (isGuardDemoMode()) {
|
|
626
|
+
return new Blob([JSON.stringify({ demo: true, generated_at: new Date().toISOString() })], { type: "application/json" });
|
|
627
|
+
}
|
|
628
|
+
const response = await fetch(guardApiInput("/v1/evidence/export"), withGuardAuth());
|
|
629
|
+
if (!response.ok) {
|
|
630
|
+
throw new Error(`Export diagnostics failed with ${response.status}`);
|
|
631
|
+
}
|
|
632
|
+
return response.blob();
|
|
633
|
+
}
|
|
@@ -185,6 +185,7 @@ export type GuardRuntimeSnapshot = {
|
|
|
185
185
|
latest_receipts: GuardReceipt[];
|
|
186
186
|
managed_installs?: GuardManagedInstall[];
|
|
187
187
|
inventory?: GuardInventoryItem[];
|
|
188
|
+
security_level?: "balanced" | "strict" | "custom";
|
|
188
189
|
};
|
|
189
190
|
|
|
190
191
|
export type GuardReceipt = {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { filterReceiptItems } from "./receipts-workspace";
|
|
2
|
+
import type { GuardReceipt } from "./guard-types";
|
|
3
|
+
|
|
4
|
+
function assert(condition: boolean, message: string): void {
|
|
5
|
+
if (!condition) {
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function makeReceipt(index: number, harness = "codex", decision = "allow"): GuardReceipt {
|
|
11
|
+
return {
|
|
12
|
+
receipt_id: `receipt-${index}`,
|
|
13
|
+
harness,
|
|
14
|
+
artifact_id: `artifact-${index}`,
|
|
15
|
+
artifact_hash: `hash-${index}`,
|
|
16
|
+
policy_decision: decision,
|
|
17
|
+
capabilities_summary: `Summary for artifact ${index}`,
|
|
18
|
+
changed_capabilities: [],
|
|
19
|
+
provenance_summary: `Provenance ${index}`,
|
|
20
|
+
user_override: null,
|
|
21
|
+
artifact_name: `Tool ${index}`,
|
|
22
|
+
source_scope: null,
|
|
23
|
+
timestamp: new Date(Date.now() - index * 60000).toISOString()
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const receipts500: GuardReceipt[] = Array.from({ length: 500 }, (_, i) => {
|
|
28
|
+
const harnesses = ["codex", "claude", "cursor", "copilot", "gemini"];
|
|
29
|
+
const decisions = ["allow", "block", "ask"];
|
|
30
|
+
return makeReceipt(i, harnesses[i % harnesses.length], decisions[i % decisions.length]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const all500 = filterReceiptItems(receipts500, "", "all", "all", "all");
|
|
34
|
+
assert(all500.length === 500, "T520: all 500 receipts should render without filter");
|
|
35
|
+
|
|
36
|
+
const codexOnly = filterReceiptItems(receipts500, "", "codex", "all", "all");
|
|
37
|
+
assert(codexOnly.length > 0, "T520: filtering by codex should return results");
|
|
38
|
+
assert(codexOnly.every((r) => r.harness === "codex"), "T520: codex filter should only return codex receipts");
|
|
39
|
+
|
|
40
|
+
const blockedOnly = filterReceiptItems(receipts500, "", "all", "block", "all");
|
|
41
|
+
assert(blockedOnly.length > 0, "T520: filtering by block decision should return results");
|
|
42
|
+
assert(blockedOnly.every((r) => r.policy_decision === "block"), "T520: decision filter should only return matching receipts");
|
|
43
|
+
|
|
44
|
+
const searchResult = filterReceiptItems(receipts500, "Tool 42", "all", "all", "all");
|
|
45
|
+
assert(searchResult.length > 0, "T520: search by name should return results");
|
|
46
|
+
|
|
47
|
+
const noResults = filterReceiptItems(receipts500, "this-will-not-match-anything-xyz", "all", "all", "all");
|
|
48
|
+
assert(noResults.length === 0, "T520: unmatched search should return empty array");
|
|
49
|
+
|
|
50
|
+
const todayFilter = filterReceiptItems(receipts500, "", "all", "all", "today");
|
|
51
|
+
assert(todayFilter.length > 0, "T520: today filter on recent receipts should return results");
|
|
52
|
+
|
|
53
|
+
const last7Filter = filterReceiptItems(receipts500, "", "all", "all", "last7");
|
|
54
|
+
assert(last7Filter.length > 0, "T520: last7 filter on recent receipts should return results");
|
|
55
|
+
|
|
56
|
+
const emptyInput: GuardReceipt[] = [];
|
|
57
|
+
const emptyResult = filterReceiptItems(emptyInput, "", "all", "all", "all");
|
|
58
|
+
assert(emptyResult.length === 0, "T520: empty input should return empty array");
|
|
@@ -18,7 +18,57 @@ type ReceiptsState =
|
|
|
18
18
|
| { kind: "error"; message: string }
|
|
19
19
|
| { kind: "ready"; items: GuardReceipt[] };
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
type DateRange = "today" | "last7" | "all";
|
|
22
|
+
|
|
23
|
+
const receiptPageSize = 50;
|
|
24
|
+
|
|
25
|
+
function sanitizeReceiptValue(value: string): string {
|
|
26
|
+
return value.replace(/\/Users\/[^/\s]+/g, "~");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function filterReceiptItems(
|
|
30
|
+
items: GuardReceipt[],
|
|
31
|
+
searchTerm: string,
|
|
32
|
+
harnessFilter: string,
|
|
33
|
+
decisionFilter: string,
|
|
34
|
+
dateRange: DateRange
|
|
35
|
+
): GuardReceipt[] {
|
|
36
|
+
const normalizedSearchTerm = searchTerm.trim().toLowerCase();
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const todayStart = new Date();
|
|
39
|
+
todayStart.setHours(0, 0, 0, 0);
|
|
40
|
+
const todayStartMs = todayStart.getTime();
|
|
41
|
+
const last7Start = now - 7 * 24 * 60 * 60 * 1000;
|
|
42
|
+
return items.filter((receipt) => {
|
|
43
|
+
const matchesHarness = harnessFilter === "all" || receipt.harness === harnessFilter;
|
|
44
|
+
const matchesDecision = decisionFilter === "all" || receipt.policy_decision === decisionFilter;
|
|
45
|
+
if (!matchesHarness || !matchesDecision) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (dateRange === "today" || dateRange === "last7") {
|
|
49
|
+
const ts = new Date(receipt.timestamp).getTime();
|
|
50
|
+
if (dateRange === "today" && ts < todayStartMs) {
|
|
51
|
+
return false;
|
|
52
|
+
} else if (dateRange === "last7" && ts < last7Start) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (normalizedSearchTerm.length === 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const searchable = [
|
|
60
|
+
receipt.artifact_name ?? "",
|
|
61
|
+
receipt.artifact_id,
|
|
62
|
+
receipt.artifact_hash,
|
|
63
|
+
receipt.harness,
|
|
64
|
+
receipt.policy_decision,
|
|
65
|
+
receipt.capabilities_summary,
|
|
66
|
+
sanitizeReceiptValue(receipt.provenance_summary),
|
|
67
|
+
(receipt.changed_capabilities ?? []).join(" ")
|
|
68
|
+
].join(" ").toLowerCase();
|
|
69
|
+
return searchable.includes(normalizedSearchTerm);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
22
72
|
|
|
23
73
|
export function ReceiptsWorkspace(props: { receipts: ReceiptsState }) {
|
|
24
74
|
if (props.receipts.kind === "loading") {
|
|
@@ -43,6 +93,7 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
43
93
|
const [searchTerm, setSearchTerm] = useState("");
|
|
44
94
|
const [harnessFilter, setHarnessFilter] = useState("all");
|
|
45
95
|
const [decisionFilter, setDecisionFilter] = useState("all");
|
|
96
|
+
const [dateRange, setDateRange] = useState<DateRange>("all");
|
|
46
97
|
const [page, setPage] = useState(1);
|
|
47
98
|
const receiptCount = props.receiptItems.length;
|
|
48
99
|
|
|
@@ -58,13 +109,17 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
58
109
|
setDecisionFilter(event.target.value);
|
|
59
110
|
}, []);
|
|
60
111
|
|
|
112
|
+
const handleDateRangeChange = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
|
113
|
+
setDateRange(event.target.value as DateRange);
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
61
116
|
const handlePreviousPage = useCallback(() => {
|
|
62
117
|
setPage((value) => Math.max(1, value - 1));
|
|
63
118
|
}, []);
|
|
64
119
|
|
|
65
120
|
useEffect(() => {
|
|
66
121
|
setPage(1);
|
|
67
|
-
}, [decisionFilter, harnessFilter, searchTerm, receiptCount]);
|
|
122
|
+
}, [decisionFilter, harnessFilter, searchTerm, dateRange, receiptCount]);
|
|
68
123
|
|
|
69
124
|
const receiptItems = props.receiptItems;
|
|
70
125
|
|
|
@@ -78,30 +133,10 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
78
133
|
[receiptItems],
|
|
79
134
|
);
|
|
80
135
|
|
|
81
|
-
const filteredReceipts = useMemo(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const matchesDecision = decisionFilter === "all" || receipt.policy_decision === decisionFilter;
|
|
86
|
-
if (!matchesHarness || !matchesDecision) {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
if (normalizedSearchTerm.length === 0) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
const searchable = [
|
|
93
|
-
receipt.artifact_name ?? "",
|
|
94
|
-
receipt.artifact_id,
|
|
95
|
-
receipt.artifact_hash,
|
|
96
|
-
receipt.harness,
|
|
97
|
-
receipt.policy_decision,
|
|
98
|
-
receipt.capabilities_summary,
|
|
99
|
-
sanitizeReceiptValue(receipt.provenance_summary),
|
|
100
|
-
receipt.changed_capabilities.join(" ")
|
|
101
|
-
].join(" ").toLowerCase();
|
|
102
|
-
return searchable.includes(normalizedSearchTerm);
|
|
103
|
-
});
|
|
104
|
-
}, [decisionFilter, harnessFilter, receiptItems, searchTerm]);
|
|
136
|
+
const filteredReceipts = useMemo(
|
|
137
|
+
() => filterReceiptItems(receiptItems, searchTerm, harnessFilter, decisionFilter, dateRange),
|
|
138
|
+
[decisionFilter, harnessFilter, receiptItems, searchTerm, dateRange],
|
|
139
|
+
);
|
|
105
140
|
|
|
106
141
|
const totalPages = Math.max(1, Math.ceil(filteredReceipts.length / receiptPageSize));
|
|
107
142
|
const currentPage = Math.min(page, totalPages);
|
|
@@ -112,7 +147,6 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
112
147
|
setPage((value) => Math.min(totalPages, value + 1));
|
|
113
148
|
}, [totalPages]);
|
|
114
149
|
|
|
115
|
-
|
|
116
150
|
if (receiptItems.length === 0) {
|
|
117
151
|
return (
|
|
118
152
|
<EmptyState
|
|
@@ -128,7 +162,7 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
128
162
|
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
|
129
163
|
<div className="space-y-1">
|
|
130
164
|
<h1 className="mt-2 text-3xl font-semibold tracking-[-0.02em] text-brand-dark">
|
|
131
|
-
|
|
165
|
+
History
|
|
132
166
|
</h1>
|
|
133
167
|
<p className="max-w-2xl text-sm leading-relaxed text-muted-foreground">
|
|
134
168
|
Search local choices by action, app, decision, or reason.
|
|
@@ -143,7 +177,7 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
143
177
|
|
|
144
178
|
<section className="rounded-[1.75rem] border border-slate-200/70 bg-white/80 p-5 shadow-sm sm:p-6">
|
|
145
179
|
<SectionLabel>Find history</SectionLabel>
|
|
146
|
-
<div className="mt-3 grid gap-3 lg:grid-cols-[minmax(0,1fr)
|
|
180
|
+
<div className="mt-3 grid gap-3 lg:grid-cols-[minmax(0,1fr)_180px_180px_180px]">
|
|
147
181
|
<ListControls
|
|
148
182
|
searchLabel="Search history"
|
|
149
183
|
searchValue={searchTerm}
|
|
@@ -156,7 +190,7 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
156
190
|
onFilterChange={handleHarnessFilterChange}
|
|
157
191
|
/>
|
|
158
192
|
<label className="block">
|
|
159
|
-
<span className="sr-only">Filter
|
|
193
|
+
<span className="sr-only">Filter history by decision</span>
|
|
160
194
|
<select
|
|
161
195
|
value={decisionFilter}
|
|
162
196
|
onChange={handleDecisionFilterChange}
|
|
@@ -168,6 +202,18 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
168
202
|
))}
|
|
169
203
|
</select>
|
|
170
204
|
</label>
|
|
205
|
+
<label className="block">
|
|
206
|
+
<span className="sr-only">Filter history by date</span>
|
|
207
|
+
<select
|
|
208
|
+
value={dateRange}
|
|
209
|
+
onChange={handleDateRangeChange}
|
|
210
|
+
className="min-h-11 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm font-medium text-brand-dark transition-colors duration-150 focus:border-brand-blue focus:outline-none focus:ring-2 focus:ring-brand-blue/20"
|
|
211
|
+
>
|
|
212
|
+
<option value="all">All time</option>
|
|
213
|
+
<option value="today">Today</option>
|
|
214
|
+
<option value="last7">Last 7 days</option>
|
|
215
|
+
</select>
|
|
216
|
+
</label>
|
|
171
217
|
</div>
|
|
172
218
|
</section>
|
|
173
219
|
|
|
@@ -202,7 +248,7 @@ function ReadyReceiptsWorkspace(props: { receiptItems: GuardReceipt[] }) {
|
|
|
202
248
|
|
|
203
249
|
function HistoryRow(props: { receipt: GuardReceipt }) {
|
|
204
250
|
const { receipt } = props;
|
|
205
|
-
const changed = receipt.changed_capabilities.join(", ") || "Nothing recorded";
|
|
251
|
+
const changed = (receipt.changed_capabilities ?? []).join(", ") || "Nothing recorded";
|
|
206
252
|
const decisionTone = receipt.policy_decision === "allow" ? "green" : receipt.policy_decision === "block" ? "purple" : "blue";
|
|
207
253
|
return (
|
|
208
254
|
<article className="px-4 py-3 transition-colors duration-150 hover:bg-surface-1/70 sm:px-5">
|
|
@@ -249,7 +295,3 @@ function HistoryRow(props: { receipt: GuardReceipt }) {
|
|
|
249
295
|
</article>
|
|
250
296
|
);
|
|
251
297
|
}
|
|
252
|
-
|
|
253
|
-
function sanitizeReceiptValue(value: string): string {
|
|
254
|
-
return value.replace(/\/Users\/[^/\s]+/g, "~");
|
|
255
|
-
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { resolveCloudIntelCopy, resolveCloudSyncHealthCopy, resolveProtectionLevelCopy } from "./runtime-overview";
|
|
2
|
+
import type { GuardCloudSyncHealth } from "./guard-types";
|
|
3
|
+
|
|
4
|
+
function assert(condition: boolean, message: string): void {
|
|
5
|
+
if (!condition) {
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const healthDisabled: GuardCloudSyncHealth = {
|
|
11
|
+
state: "disabled",
|
|
12
|
+
label: "Sync disabled",
|
|
13
|
+
detail: "Cloud sync is turned off on this machine.",
|
|
14
|
+
pending_events: 0,
|
|
15
|
+
last_synced_at: null,
|
|
16
|
+
next_retry_after: null
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const healthHealthy: GuardCloudSyncHealth = {
|
|
20
|
+
state: "healthy",
|
|
21
|
+
label: "Sync healthy",
|
|
22
|
+
detail: "Cloud sync is running normally.",
|
|
23
|
+
pending_events: 0,
|
|
24
|
+
last_synced_at: new Date().toISOString(),
|
|
25
|
+
next_retry_after: null
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const localOnlyCopy = resolveCloudIntelCopy("local_only");
|
|
29
|
+
assert(localOnlyCopy.label === "Offline, free", "T507: local_only label should be 'Offline, free'");
|
|
30
|
+
assert(localOnlyCopy.detail.length > 0, "T507: local_only detail should not be empty");
|
|
31
|
+
assert(localOnlyCopy.detail.includes("locally"), "T507: local_only detail should mention 'locally'");
|
|
32
|
+
|
|
33
|
+
const localOnlySyncCopy = resolveCloudSyncHealthCopy(healthDisabled);
|
|
34
|
+
assert(localOnlySyncCopy.label === healthDisabled.label, "T507: cloud sync health label should match");
|
|
35
|
+
assert(localOnlySyncCopy.detail === healthDisabled.detail, "T507: cloud sync health detail should match");
|
|
36
|
+
|
|
37
|
+
const protectionBalanced = resolveProtectionLevelCopy("balanced");
|
|
38
|
+
assert(protectionBalanced.includes("secrets"), "T507: balanced description should mention secrets");
|
|
39
|
+
|
|
40
|
+
const pairedActiveCopy = resolveCloudIntelCopy("paired_active");
|
|
41
|
+
assert(pairedActiveCopy.label === "Synced, pro", "T508: paired_active label should be 'Synced, pro'");
|
|
42
|
+
assert(pairedActiveCopy.detail.length > 0, "T508: paired_active detail should not be empty");
|
|
43
|
+
assert(pairedActiveCopy.detail.includes("Guard Cloud"), "T508: paired_active detail should mention Guard Cloud");
|
|
44
|
+
|
|
45
|
+
const pairedWaitingCopy = resolveCloudIntelCopy("paired_waiting");
|
|
46
|
+
assert(pairedWaitingCopy.label === "Pairing…", "T508: paired_waiting label should be 'Pairing…'");
|
|
47
|
+
|
|
48
|
+
const pairedActiveSyncCopy = resolveCloudSyncHealthCopy(healthHealthy);
|
|
49
|
+
assert(pairedActiveSyncCopy.label === healthHealthy.label, "T508: healthy sync label should match");
|
|
50
|
+
|
|
51
|
+
const protectionStrict = resolveProtectionLevelCopy("strict");
|
|
52
|
+
assert(protectionStrict.includes("network"), "T508: strict description should mention network");
|
|
53
|
+
|
|
54
|
+
const protectionCustom = resolveProtectionLevelCopy("custom");
|
|
55
|
+
assert(protectionCustom.includes("Custom"), "T508: custom description should mention Custom");
|