plugin-scanner 2.0.71__tar.gz → 2.0.72__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.71 → plugin_scanner-2.0.72}/PKG-INFO +1 -1
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/pyproject.toml +1 -1
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/approvals.py +3 -2
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/server.py +51 -54
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_approvals.py +125 -1
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.dockerignore +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.gitignore +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/Dockerfile +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/requirements.txt +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/commands.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_runtime.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/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.72
|
|
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,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.72"
|
|
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.72"
|
|
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"
|
|
@@ -119,7 +119,7 @@ def apply_approval_resolution(
|
|
|
119
119
|
if scope == "publisher" and not isinstance(request.get("publisher"), str):
|
|
120
120
|
raise ValueError(f"Approval request {request_id} has no publisher scope to approve.")
|
|
121
121
|
decision = PolicyDecision(
|
|
122
|
-
harness=str(request["harness"]),
|
|
122
|
+
harness="*" if scope == "global" else str(request["harness"]),
|
|
123
123
|
scope=scope,
|
|
124
124
|
action="allow" if action == "allow" else "block",
|
|
125
125
|
artifact_id=str(request["artifact_id"]) if scope == "artifact" else None,
|
|
@@ -130,8 +130,9 @@ def apply_approval_resolution(
|
|
|
130
130
|
)
|
|
131
131
|
store.upsert_policy(decision, now or _now())
|
|
132
132
|
resolved_at = now or _now()
|
|
133
|
+
resolution_harness = None if scope == "global" else str(request["harness"])
|
|
133
134
|
resolved_ids = store.resolve_matching_approval_requests(
|
|
134
|
-
harness=
|
|
135
|
+
harness=resolution_harness,
|
|
135
136
|
scope=scope,
|
|
136
137
|
artifact_id=str(request["artifact_id"]) if scope == "artifact" else None,
|
|
137
138
|
workspace=workspace if scope == "workspace" else None,
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/guard/daemon/server.py
RENAMED
|
@@ -26,6 +26,7 @@ from ..store import GuardStore
|
|
|
26
26
|
from .manager import (
|
|
27
27
|
GUARD_DAEMON_COMPATIBILITY_VERSION,
|
|
28
28
|
clear_guard_daemon_state,
|
|
29
|
+
load_guard_daemon_auth_token,
|
|
29
30
|
write_guard_daemon_state,
|
|
30
31
|
)
|
|
31
32
|
|
|
@@ -59,18 +60,19 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
59
60
|
_MAX_BODY_BYTES = 1_000_000
|
|
60
61
|
|
|
61
62
|
def do_OPTIONS(self) -> None:
|
|
62
|
-
|
|
63
|
-
if
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
self._write_empty(
|
|
69
|
-
status=200,
|
|
70
|
-
extra_headers=self._cors_headers(origin, allow_methods="GET, POST, OPTIONS"),
|
|
71
|
-
)
|
|
63
|
+
origin = self._normalize_origin(self.headers.get("Origin"))
|
|
64
|
+
if origin is None:
|
|
65
|
+
self._write_empty(status=400)
|
|
66
|
+
return
|
|
67
|
+
if not self._origin_is_allowed():
|
|
68
|
+
self._write_empty(status=403)
|
|
72
69
|
return
|
|
73
|
-
self._write_empty(
|
|
70
|
+
self._write_empty(
|
|
71
|
+
status=200,
|
|
72
|
+
extra_headers=self._cors_headers(
|
|
73
|
+
origin, allow_methods="GET, POST, OPTIONS", allow_headers="Content-Type, X-Guard-Token"
|
|
74
|
+
),
|
|
75
|
+
)
|
|
74
76
|
|
|
75
77
|
def do_GET(self) -> None:
|
|
76
78
|
store = self.server.store # type: ignore[attr-defined]
|
|
@@ -205,11 +207,19 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
205
207
|
if parsed.path != "/v1/connect/complete" and not self._origin_is_allowed():
|
|
206
208
|
self._write_json({"error": "forbidden_origin"}, status=403)
|
|
207
209
|
return
|
|
210
|
+
path_parts = [part for part in parsed.path.split("/") if part]
|
|
211
|
+
if self._requires_header_token(parsed.path, path_parts) and not self._header_token_is_valid():
|
|
212
|
+
origin = self._normalize_origin(self.headers.get("Origin"))
|
|
213
|
+
self._write_json(
|
|
214
|
+
{"error": "unauthorized"},
|
|
215
|
+
status=401,
|
|
216
|
+
extra_headers=self._cors_headers(origin) if origin is not None else None,
|
|
217
|
+
)
|
|
218
|
+
return
|
|
208
219
|
payload, body_error = self._load_request_body()
|
|
209
220
|
if body_error is not None:
|
|
210
221
|
self._write_json({"error": body_error}, status=400)
|
|
211
222
|
return
|
|
212
|
-
path_parts = [part for part in parsed.path.split("/") if part]
|
|
213
223
|
if parsed.path == "/v1/initialize":
|
|
214
224
|
self._handle_initialize(payload)
|
|
215
225
|
return
|
|
@@ -217,78 +227,42 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
217
227
|
self._handle_claude_hook(payload, parsed.query)
|
|
218
228
|
return
|
|
219
229
|
if parsed.path == "/v1/clients/attach":
|
|
220
|
-
if not self._header_token_is_valid():
|
|
221
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
222
|
-
return
|
|
223
230
|
self._handle_client_attach(payload)
|
|
224
231
|
return
|
|
225
232
|
if parsed.path == "/v1/clients/heartbeat":
|
|
226
|
-
if not self._header_token_is_valid():
|
|
227
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
228
|
-
return
|
|
229
233
|
self._handle_client_heartbeat(payload)
|
|
230
234
|
return
|
|
231
235
|
if parsed.path == "/v1/sessions/start":
|
|
232
|
-
if not self._header_token_is_valid():
|
|
233
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
234
|
-
return
|
|
235
236
|
self._handle_session_start(payload)
|
|
236
237
|
return
|
|
237
238
|
if parsed.path == "/v1/operations/start":
|
|
238
|
-
if not self._header_token_is_valid():
|
|
239
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
240
|
-
return
|
|
241
239
|
self._handle_operation_start(payload)
|
|
242
240
|
return
|
|
243
241
|
if parsed.path == "/v1/connect/requests":
|
|
244
|
-
if not self._header_token_is_valid():
|
|
245
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
246
|
-
return
|
|
247
242
|
self._handle_connect_request_create(payload)
|
|
248
243
|
return
|
|
249
244
|
if parsed.path == "/v1/connect/complete":
|
|
250
245
|
self._handle_connect_complete(payload)
|
|
251
246
|
return
|
|
252
247
|
if parsed.path == "/v1/connect/result":
|
|
253
|
-
if not self._header_token_is_valid():
|
|
254
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
255
|
-
return
|
|
256
248
|
self._handle_connect_result_update(payload)
|
|
257
249
|
return
|
|
258
250
|
if parsed.path == "/v1/operations/block":
|
|
259
|
-
if not self._header_token_is_valid():
|
|
260
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
261
|
-
return
|
|
262
251
|
self._handle_operation_block(payload)
|
|
263
252
|
return
|
|
264
253
|
if len(path_parts) == 4 and path_parts[:2] == ["v1", "operations"] and path_parts[3] == "items":
|
|
265
|
-
if not self._header_token_is_valid():
|
|
266
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
267
|
-
return
|
|
268
254
|
self._handle_operation_item(path_parts[2], payload)
|
|
269
255
|
return
|
|
270
256
|
if len(path_parts) == 4 and path_parts[:2] == ["v1", "operations"] and path_parts[3] == "status":
|
|
271
|
-
if not self._header_token_is_valid():
|
|
272
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
273
|
-
return
|
|
274
257
|
self._handle_operation_status(path_parts[2], payload)
|
|
275
258
|
return
|
|
276
259
|
if parsed.path == "/v1/policy/decisions":
|
|
277
|
-
if not self._header_token_is_valid():
|
|
278
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
279
|
-
return
|
|
280
260
|
self._handle_policy_upsert(payload)
|
|
281
261
|
return
|
|
282
262
|
if parsed.path == "/v1/policy/clear":
|
|
283
|
-
if not self._header_token_is_valid():
|
|
284
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
285
|
-
return
|
|
286
263
|
self._handle_policy_clear(payload)
|
|
287
264
|
return
|
|
288
265
|
if parsed.path == "/v1/settings":
|
|
289
|
-
if not self._header_token_is_valid():
|
|
290
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
291
|
-
return
|
|
292
266
|
self._handle_settings_update(payload)
|
|
293
267
|
return
|
|
294
268
|
request_id, action, matched = self._resolve_request_action(path_parts, payload)
|
|
@@ -296,9 +270,6 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
296
270
|
self.send_response(404)
|
|
297
271
|
self.end_headers()
|
|
298
272
|
return
|
|
299
|
-
if not self._header_token_is_valid():
|
|
300
|
-
self._write_json({"error": "unauthorized"}, status=401)
|
|
301
|
-
return
|
|
302
273
|
if action is None:
|
|
303
274
|
self._write_json({"resolved": False, "error": "missing_required_fields"}, status=400)
|
|
304
275
|
return
|
|
@@ -868,11 +839,16 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
868
839
|
return f"{parsed.scheme}://{host}{port_suffix}"
|
|
869
840
|
|
|
870
841
|
@staticmethod
|
|
871
|
-
def _cors_headers(
|
|
842
|
+
def _cors_headers(
|
|
843
|
+
origin: str,
|
|
844
|
+
*,
|
|
845
|
+
allow_methods: str = "POST, OPTIONS",
|
|
846
|
+
allow_headers: str = "Content-Type, X-Guard-Token",
|
|
847
|
+
) -> dict[str, str]:
|
|
872
848
|
return {
|
|
873
849
|
"Access-Control-Allow-Origin": origin,
|
|
874
850
|
"Access-Control-Allow-Methods": allow_methods,
|
|
875
|
-
"Access-Control-Allow-Headers":
|
|
851
|
+
"Access-Control-Allow-Headers": allow_headers,
|
|
876
852
|
"Vary": "Origin",
|
|
877
853
|
}
|
|
878
854
|
|
|
@@ -959,6 +935,27 @@ class _GuardDaemonHandler(BaseHTTPRequestHandler):
|
|
|
959
935
|
return path_parts[1], action.strip(), True
|
|
960
936
|
return None, None, False
|
|
961
937
|
|
|
938
|
+
@staticmethod
|
|
939
|
+
def _requires_header_token(path: str, path_parts: list[str]) -> bool:
|
|
940
|
+
if path in {
|
|
941
|
+
"/v1/clients/attach",
|
|
942
|
+
"/v1/clients/heartbeat",
|
|
943
|
+
"/v1/sessions/start",
|
|
944
|
+
"/v1/operations/start",
|
|
945
|
+
"/v1/connect/requests",
|
|
946
|
+
"/v1/connect/result",
|
|
947
|
+
"/v1/operations/block",
|
|
948
|
+
"/v1/policy/decisions",
|
|
949
|
+
"/v1/policy/clear",
|
|
950
|
+
"/v1/settings",
|
|
951
|
+
}:
|
|
952
|
+
return True
|
|
953
|
+
if len(path_parts) == 4 and path_parts[:2] == ["v1", "operations"] and path_parts[3] in {"items", "status"}:
|
|
954
|
+
return True
|
|
955
|
+
if len(path_parts) == 4 and path_parts[:2] == ["v1", "requests"] and path_parts[3] in {"approve", "block"}:
|
|
956
|
+
return True
|
|
957
|
+
return len(path_parts) == 3 and path_parts[0] == "approvals" and path_parts[2] == "decision"
|
|
958
|
+
|
|
962
959
|
def _write_json(
|
|
963
960
|
self,
|
|
964
961
|
payload: dict[str, Any],
|
|
@@ -1080,7 +1077,7 @@ class GuardDaemonServer:
|
|
|
1080
1077
|
self._server = _GuardDaemonHttpServer((host, port), _GuardDaemonHandler)
|
|
1081
1078
|
self._server.store = store
|
|
1082
1079
|
self._server.runtime = GuardSurfaceRuntime(store)
|
|
1083
|
-
self._server.auth_token = uuid.uuid4().hex
|
|
1080
|
+
self._server.auth_token = load_guard_daemon_auth_token(store.guard_home) or uuid.uuid4().hex
|
|
1084
1081
|
self._server.runtime_host = host
|
|
1085
1082
|
self._server.runtime_session_id = uuid.uuid4().hex
|
|
1086
1083
|
self._server.runtime_started_at = _now()
|
|
@@ -418,6 +418,44 @@ class TestGuardApprovals:
|
|
|
418
418
|
assert resolved["status"] == "resolved"
|
|
419
419
|
assert store.get_approval_request("req-b")["status"] == "resolved"
|
|
420
420
|
|
|
421
|
+
def test_guard_global_scope_resolution_clears_pending_requests_across_harnesses(self, tmp_path):
|
|
422
|
+
store = GuardStore(tmp_path / "guard-home")
|
|
423
|
+
for request_id, harness in (("req-codex", "codex"), ("req-copilot", "copilot")):
|
|
424
|
+
store.add_approval_request(
|
|
425
|
+
GuardApprovalRequest(
|
|
426
|
+
request_id=request_id,
|
|
427
|
+
harness=harness,
|
|
428
|
+
artifact_id=f"{harness}:project:item",
|
|
429
|
+
artifact_name=f"{harness}-item",
|
|
430
|
+
artifact_hash=f"hash-{request_id}",
|
|
431
|
+
policy_action="require-reapproval",
|
|
432
|
+
recommended_scope="global",
|
|
433
|
+
changed_fields=("args",),
|
|
434
|
+
source_scope="project",
|
|
435
|
+
config_path=str(tmp_path / harness / ".config" / "guard.toml"),
|
|
436
|
+
review_command=f"hol-guard approvals approve {request_id}",
|
|
437
|
+
approval_url=f"http://127.0.0.1:4455/approvals/{request_id}",
|
|
438
|
+
),
|
|
439
|
+
"2026-04-11T00:00:00+00:00",
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
resolved = apply_approval_resolution(
|
|
443
|
+
store=store,
|
|
444
|
+
request_id="req-codex",
|
|
445
|
+
action="allow",
|
|
446
|
+
scope="global",
|
|
447
|
+
workspace=None,
|
|
448
|
+
reason="trusted globally",
|
|
449
|
+
now="2026-04-11T00:02:00+00:00",
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
pending = store.list_approval_requests(status="pending", limit=None)
|
|
453
|
+
decisions = store.list_policy_decisions()
|
|
454
|
+
|
|
455
|
+
assert resolved["status"] == "resolved"
|
|
456
|
+
assert pending == []
|
|
457
|
+
assert decisions[0]["harness"] == "*"
|
|
458
|
+
|
|
421
459
|
def test_guard_broad_scope_resolution_clears_more_than_default_pending_page(self, tmp_path):
|
|
422
460
|
store = GuardStore(tmp_path / "guard-home")
|
|
423
461
|
for index in range(520):
|
|
@@ -692,6 +730,20 @@ class TestGuardApprovals:
|
|
|
692
730
|
|
|
693
731
|
assert daemon_manager_module.load_guard_daemon_url(guard_home) is None
|
|
694
732
|
|
|
733
|
+
def test_guard_daemon_server_reuses_existing_auth_token(self, tmp_path):
|
|
734
|
+
store = GuardStore(tmp_path / "guard-home")
|
|
735
|
+
token_path = store.guard_home / "daemon-auth-token"
|
|
736
|
+
token_path.parent.mkdir(parents=True, exist_ok=True)
|
|
737
|
+
token_path.write_text("persisted-token", encoding="utf-8")
|
|
738
|
+
daemon = GuardDaemonServer(store, host="127.0.0.1", port=0)
|
|
739
|
+
|
|
740
|
+
try:
|
|
741
|
+
daemon.start()
|
|
742
|
+
assert daemon._server.auth_token == "persisted-token"
|
|
743
|
+
assert token_path.read_text(encoding="utf-8").strip() == "persisted-token"
|
|
744
|
+
finally:
|
|
745
|
+
daemon.stop()
|
|
746
|
+
|
|
695
747
|
def test_guard_daemon_serves_approval_queue_and_resolves_requests(self, tmp_path):
|
|
696
748
|
store = GuardStore(tmp_path / "guard-home")
|
|
697
749
|
store.add_approval_request(
|
|
@@ -1290,7 +1342,7 @@ class TestGuardApprovals:
|
|
|
1290
1342
|
request = urllib.request.Request(
|
|
1291
1343
|
f"http://127.0.0.1:{daemon.port}/approvals/missing/decision",
|
|
1292
1344
|
data=b"{not-json",
|
|
1293
|
-
headers=
|
|
1345
|
+
headers=_guard_json_headers(daemon._server.auth_token),
|
|
1294
1346
|
method="POST",
|
|
1295
1347
|
)
|
|
1296
1348
|
try:
|
|
@@ -1374,6 +1426,78 @@ class TestGuardApprovals:
|
|
|
1374
1426
|
assert status == 403
|
|
1375
1427
|
assert payload["error"] == "forbidden_origin"
|
|
1376
1428
|
|
|
1429
|
+
def test_guard_daemon_rejects_cross_origin_options_requests(self, tmp_path):
|
|
1430
|
+
store = GuardStore(tmp_path / "guard-home")
|
|
1431
|
+
daemon = GuardDaemonServer(store, host="127.0.0.1", port=0)
|
|
1432
|
+
daemon.start()
|
|
1433
|
+
|
|
1434
|
+
try:
|
|
1435
|
+
request = urllib.request.Request(
|
|
1436
|
+
f"http://127.0.0.1:{daemon.port}/v1/requests/missing/approve",
|
|
1437
|
+
headers={"Origin": "https://evil.example"},
|
|
1438
|
+
method="OPTIONS",
|
|
1439
|
+
)
|
|
1440
|
+
try:
|
|
1441
|
+
urllib.request.urlopen(request, timeout=5)
|
|
1442
|
+
except urllib.error.HTTPError as error:
|
|
1443
|
+
status = error.code
|
|
1444
|
+
else:
|
|
1445
|
+
raise AssertionError("expected HTTPError for disallowed preflight origin")
|
|
1446
|
+
finally:
|
|
1447
|
+
daemon.stop()
|
|
1448
|
+
|
|
1449
|
+
assert status == 403
|
|
1450
|
+
|
|
1451
|
+
def test_guard_daemon_allows_local_options_requests_with_guard_headers(self, tmp_path):
|
|
1452
|
+
store = GuardStore(tmp_path / "guard-home")
|
|
1453
|
+
daemon = GuardDaemonServer(store, host="127.0.0.1", port=0)
|
|
1454
|
+
daemon.start()
|
|
1455
|
+
|
|
1456
|
+
try:
|
|
1457
|
+
request = urllib.request.Request(
|
|
1458
|
+
f"http://127.0.0.1:{daemon.port}/v1/requests/missing/approve",
|
|
1459
|
+
headers={"Origin": f"http://127.0.0.1:{daemon.port}"},
|
|
1460
|
+
method="OPTIONS",
|
|
1461
|
+
)
|
|
1462
|
+
with urllib.request.urlopen(request, timeout=5) as response:
|
|
1463
|
+
allow_headers = response.headers.get("Access-Control-Allow-Headers")
|
|
1464
|
+
status = response.status
|
|
1465
|
+
finally:
|
|
1466
|
+
daemon.stop()
|
|
1467
|
+
|
|
1468
|
+
assert status == 200
|
|
1469
|
+
assert allow_headers == "Content-Type, X-Guard-Token"
|
|
1470
|
+
|
|
1471
|
+
def test_guard_daemon_includes_cors_headers_on_unauthorized_local_post(self, tmp_path):
|
|
1472
|
+
store = GuardStore(tmp_path / "guard-home")
|
|
1473
|
+
daemon = GuardDaemonServer(store, host="127.0.0.1", port=0)
|
|
1474
|
+
daemon.start()
|
|
1475
|
+
|
|
1476
|
+
try:
|
|
1477
|
+
request = urllib.request.Request(
|
|
1478
|
+
f"http://127.0.0.1:{daemon.port}/v1/requests/missing/approve",
|
|
1479
|
+
data=json.dumps({"scope": "artifact"}).encode("utf-8"),
|
|
1480
|
+
headers={
|
|
1481
|
+
"Content-Type": "application/json",
|
|
1482
|
+
"Origin": f"http://127.0.0.1:{daemon.port}",
|
|
1483
|
+
},
|
|
1484
|
+
method="POST",
|
|
1485
|
+
)
|
|
1486
|
+
try:
|
|
1487
|
+
urllib.request.urlopen(request, timeout=5)
|
|
1488
|
+
except urllib.error.HTTPError as error:
|
|
1489
|
+
status = error.code
|
|
1490
|
+
payload = json.loads(error.read().decode("utf-8"))
|
|
1491
|
+
allow_origin = error.headers.get("Access-Control-Allow-Origin")
|
|
1492
|
+
else:
|
|
1493
|
+
raise AssertionError("expected HTTPError for missing auth token")
|
|
1494
|
+
finally:
|
|
1495
|
+
daemon.stop()
|
|
1496
|
+
|
|
1497
|
+
assert status == 401
|
|
1498
|
+
assert payload["error"] == "unauthorized"
|
|
1499
|
+
assert allow_origin == f"http://127.0.0.1:{daemon.port}"
|
|
1500
|
+
|
|
1377
1501
|
def test_guard_daemon_rejects_spoofed_localhost_origin_post_requests(self, tmp_path):
|
|
1378
1502
|
store = GuardStore(tmp_path / "guard-home")
|
|
1379
1503
|
daemon = GuardDaemonServer(store, host="127.0.0.1", port=0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/dashboard/src/approval-center-primitives.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/best_practices.py
RENAMED
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/code_quality.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/ecosystem_common.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/manifest_support.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/marketplace.py
RENAMED
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/mcp_security.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/checks/skill_security.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plugin_scanner-2.0.71 → plugin_scanner-2.0.72}/src/codex_plugin_scanner/ecosystems/__init__.py
RENAMED
|
File without changes
|