mcp-warden-cli 2.2.0__tar.gz → 2.3.0__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.
- mcp_warden_cli-2.3.0/.github/workflows/normalization.yml +43 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CHANGELOG.md +24 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/DOCUMENTATION_INDEX.md +26 -3
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/PKG-INFO +23 -2
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/README.md +22 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/RELEASING.md +27 -11
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/SYSTEM_CONTEXT_DIAGRAM.md +28 -3
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action/requirements.lock +3 -3
- mcp_warden_cli-2.3.0/components/normalizer/Dockerfile +13 -0
- mcp_warden_cli-2.3.0/components/normalizer/README.md +93 -0
- mcp_warden_cli-2.3.0/components/normalizer/THIRD_PARTY_NOTICES.md +18 -0
- mcp_warden_cli-2.3.0/components/normalizer/formats.py +110 -0
- mcp_warden_cli-2.3.0/components/normalizer/formats_containers.py +173 -0
- mcp_warden_cli-2.3.0/components/normalizer/formats_markdown.py +80 -0
- mcp_warden_cli-2.3.0/components/normalizer/formats_pdf.py +122 -0
- mcp_warden_cli-2.3.0/components/normalizer/formats_structured.py +192 -0
- mcp_warden_cli-2.3.0/components/normalizer/requirements.lock +7 -0
- mcp_warden_cli-2.3.0/components/normalizer/worker.py +69 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/AGENT_GATES.md +9 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/CHECKS.md +1 -0
- mcp_warden_cli-2.3.0/docs/CONTENT_NORMALIZATION.md +195 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/RESULT_INSPECTION.md +6 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/SPEC.md +6 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/WARDEN_LOCK_SCHEMA.md +4 -0
- mcp_warden_cli-2.3.0/docs/plans/2026-11-14-op-reference-ids.md +45 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/drift.ts +12 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/pyproject.toml +1 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/requirements-dev.lock +3 -3
- mcp_warden_cli-2.3.0/scripts/qualify_normalizer.sh +29 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/__init__.py +5 -3
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/auth_audit.py +6 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/auth_refs.py +31 -3
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli.py +2 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_guard.py +38 -1
- mcp_warden_cli-2.3.0/src/mcp_warden/cli_normalize.py +59 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/drift.py +17 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard.py +5 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_banner.py +8 -4
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_loop.py +19 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_result.py +16 -2
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/inspector.py +32 -1
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization.py +215 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_guard.py +60 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_ingress.py +43 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_inspection.py +152 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_ipc.py +113 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_models.py +78 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_sandbox.py +226 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_trace.py +49 -0
- mcp_warden_cli-2.3.0/src/mcp_warden/normalization_validation.py +95 -0
- mcp_warden_cli-2.3.0/tests/fuzz/test_fuzz_normalization.py +54 -0
- mcp_warden_cli-2.3.0/tests/test_auth_refs_op_ids.py +99 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_drift.py +32 -0
- mcp_warden_cli-2.3.0/tests/test_normalization_contract.py +47 -0
- mcp_warden_cli-2.3.0/tests/test_normalization_coordinator.py +125 -0
- mcp_warden_cli-2.3.0/tests/test_normalization_e2e.py +125 -0
- mcp_warden_cli-2.3.0/tests/test_normalization_integration.py +232 -0
- mcp_warden_cli-2.3.0/tests/test_normalization_sandbox.py +212 -0
- mcp_warden_cli-2.3.0/tests/test_normalizer_formats.py +403 -0
- mcp_warden_cli-2.3.0/vectors/cases/drift-digest-mismatch-unexplained.json +119 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/manifest.json +6 -1
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/tools/generate.py +1 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/action-test.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/deps-locked.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/docs.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/examples.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/integrity-gate.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/release.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/sigstore-fixture.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.gitignore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.gitleaks.toml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.pre-commit-hooks.yaml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CODEOWNERS +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CODE_OF_CONDUCT.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CONTRIBUTING.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/LICENSE +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/Makefile +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/SECURITY.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action/build-requirements.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/AGENT_TRUST_KERNEL.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/ARTIFACT_TRUST.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/COMMUNITY_CORPUS.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/CONTENT_ENVELOPE.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/DECISION_RECEIPTS.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/DOCTOR.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/GUARD_PROXY.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/GUARD_PROXY_V3.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/PIN_CHECK_DEMO.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/POLICY_ENFORCEMENT.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/POLICY_MODEL.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/SIGNING.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/THREAT_MODEL.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/THREAT_MODEL_V2.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/WARDEN_LOCK_EXAMPLE.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/archive/2026-10-02-runtime-cli-examples.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/archive/2026-10-04-readme-community-consensus.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-18-agent-trust-kernel-design.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-18-content-envelope-design.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-decision-receipts-design.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-decision-receipts-implementation.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-pdp-pep-design.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-02-pypi-automation-repair.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-02-tool-integrity-upgrade.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-03-checkpoint-artifact-trust.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-04-dse717-council-fixes.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-04-dse717-reconciliation.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/artifact-trust.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/checklist.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/comparison.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/decision-receipts.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/index.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/lock-format.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/pin-in-ci.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/quickstart.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/rug-pull.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/tool-poisoning.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/evidence-fail.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/evidence-pass.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/gate-policy.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/mcp-config-audit-demo.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/matrix-multiple-servers.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/pin-on-merge-check-on-pr.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/private-repo-no-sarif.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/sarif-upload.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/gitlab-ci/.gitlab-ci.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-everything/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-everything/warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-memory/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-memory/warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-sequential-thinking/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-sequential-thinking/warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pre-commit/.pre-commit-config.yaml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/mkdocs.yml +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/.gitignore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/LICENSE +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/package-lock.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/package.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/capabilities.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/digest.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/index.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/jcs.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/lock.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/py.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/skeleton.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/test/vectors.test.ts +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/tsconfig.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/scripts/verify_pypi_oidc.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/adapter_conformance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/artifact_payload.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/artifact_trust.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/capture.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/check_core.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks_secret.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks_supply.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_auth.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_corpus.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_deploy_gate.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_diff.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_doctor.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_lock.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_sign.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_trust.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/content_envelope.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/content_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_coordinate.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_trust.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_verify.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_governor.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_receipts.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/deploy_gate.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_discovery.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_funnel.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_jsonc.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_paths.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/drift_tool_metadata.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/emit_res.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/emitters.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/enforcement_result_v2.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_coordinator.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_floor.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_helpers.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_latch.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_recovery.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_reference.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_state.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/executable_bundle.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/framing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/governance_integrity.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/governed_decision.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_io.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_lifecycle.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_list_gate.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_strict.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/handler_identity.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/hashing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/lockfile.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/net_rules.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_decision.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement_v2.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement_v2_helpers.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_eval.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_model.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/precommit.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/provenance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_conformance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_conformance_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_kernel.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_log.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_projection.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_replay.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_verification.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/redact.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_catalog.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_dns.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_net.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_rules.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/result_inspection.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/rule_engine.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/rule_models.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/schema_diff.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/signer_authorization.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/signing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/tokenizer.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/wire_block.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/__init__.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/dse717_council_fixtures.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/_sdk_compat.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/capability_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean.warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean_listchange.warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/attesters.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__clean/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__clean/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__clean/1.0.0/bob.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__clean/1.0.0/bob.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__corrupt/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__corrupt/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__nosig/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__other/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__other/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__other/1.0.0/bob.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__other/1.0.0/bob.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__solo/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__solo/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__split/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__split/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__split/1.0.0/bob.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__split/1.0.0/bob.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__stranger/1.0.0/mallory.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__stranger/1.0.0/mallory.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__unpinned/1.0.0/carol.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__unpinned/1.0.0/carol.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__wrongsig/1.0.0/alice.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/locks/schema-4/npm/@example__wrongsig/1.0.0/alice.lock.sigstore +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/crash_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/fault_guard_launcher.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/gen_corpus.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/legacy-v3.warden.lock +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/listchange_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/mutated_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/overcap_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/poison_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/tool_integrity_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/tool_metadata_listchange_server.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/__init__.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/conftest.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_ansi.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_content_envelope.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_domain.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_framing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_policy_decision.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_receipts.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_redact.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/receipt_fixtures.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_action_yml.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_adapter_conformance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_agent_gates_examples.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_artifact_trust.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_artifact_trust_integration.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_auth_audit.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_capabilities.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_http.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_model_dump.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_page_cap.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_pagination.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_checks.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_cli_trust.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_cli_version.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_content_envelope.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_corpus.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_corpus_cli.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_decision_receipts.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_deploy_gate.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_diff.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor_cli.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor_security.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_fixes.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_floors.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_rotation.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_review_regressions.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_e2e_pin_check.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_emitters.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_coordinator.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_recovery.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_state.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_state_v2_contract.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_framing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_banner.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_platform.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_posture.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_proxy.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_strict.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_v3.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_windows.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_handler_boundary.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_hashing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_inspect_parity.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_inspection_policy.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_lock_sign.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_lockfile.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_decision.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_enforcement.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_enforcement_v2.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_precommit.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_provenance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_conformance.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_hardening.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_log.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_projection.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_replay.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_verification.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_release_oidc.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_res_dns.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_result_inspection.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_rule_engine.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_schema_diff.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_schema_diff_refs.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_signing.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_signing_unit.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_spec_consistency.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_spec_vectors.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tokenizer.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tool_integrity.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tool_integrity_guard.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_wire_block.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_workflow_pins.py +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/README.md +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-control-escapes.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-deep-nesting.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-depth-512-accepted.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-array.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-object.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-string.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-key-escapes.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-nested-arrays.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-numbers-boundaries.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-numbers-es6.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-scalars.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-sorted-keys-utf16.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-surrogate-key-order.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-unicode-literal.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-absence-rules.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-capabilities-and-refs.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-clean-fixture.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-entry-sorting-astral.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-entry-sorting.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-enum-constraints-skeleton.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-http-url-server.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-malformed-input-schema.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-minimal-single-tool.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-empty.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-full.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-null.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-capability-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-capability-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-description-and-schema.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-description-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-inspection-policy-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-mixed-multi-entry.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-no-drift.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-additional-props-opened-to-object.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-additional-props-opened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-array-items-recursed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-bound-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-maxlength-up.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-minimum-lowered.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-pattern-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-required-to-optional.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-tightened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-cosmetic-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-disjoint-is-widened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-narrowed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-widened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-opaque-ref.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-ref-redacted.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-v1-fallback.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-constraint-relaxed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-cosmetic-modified.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-extension-null.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-local-ref.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-ref-redacted.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-type-broadened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-pattern-changed-tightened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-per-fact-emission.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-property-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-property-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-ref-resolved-granular.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-unconstrained-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-any-to-typed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-broadened.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-changed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-narrowed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-unconstrained-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-version-migrated.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-server-identity-url.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-server-identity.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-added.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-destructiveHint.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-explicit-null.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-extension.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-idempotentHint.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-nested-null.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-openWorldHint.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-readOnlyHint.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-removed.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-unapproved-change.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-v3-to-v4-migration.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-v3-unapproved-migration.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-deep-nesting-2000.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-depth-513-rejected.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-invalid-json.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-lock-depth-1200-rejected.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-missing-overall-digest.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-missing-pin.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-schema-version-above-implemented.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-schema-version-not-integer.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-server-missing-command-digest.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-tool-missing-entry-digest.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-tools-not-array.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-high.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-key.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-low.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-v4-missing-annotations_hash.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-v4-missing-output_schema_hash.json +0 -0
- {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-v4-missing-output_schema_skeleton.json +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Normalization qualification
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: normalizer-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
qualify:
|
|
18
|
+
name: Linux isolated normalization
|
|
19
|
+
runs-on: ubuntu-24.04
|
|
20
|
+
timeout-minutes: 15
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
- name: Install coordinator and standalone parser test closure
|
|
27
|
+
run: |
|
|
28
|
+
pip install --require-hashes -r requirements-dev.lock
|
|
29
|
+
pip install --require-hashes -r components/normalizer/requirements.lock
|
|
30
|
+
pip install --no-deps -e .
|
|
31
|
+
- name: Build exact immutable worker
|
|
32
|
+
run: |
|
|
33
|
+
docker build --iidfile "$RUNNER_TEMP/normalizer-image" -f components/normalizer/Dockerfile .
|
|
34
|
+
echo "NORMALIZER_TEST_IMAGE=$(cat "$RUNNER_TEMP/normalizer-image")" >> "$GITHUB_ENV"
|
|
35
|
+
- name: Audit independent parser closure
|
|
36
|
+
run: |
|
|
37
|
+
python -m venv "$RUNNER_TEMP/parser-audit"
|
|
38
|
+
"$RUNNER_TEMP/parser-audit/bin/pip" install "pip-audit==2.9.0"
|
|
39
|
+
"$RUNNER_TEMP/parser-audit/bin/python" -m pip_audit --disable-pip --require-hashes -r components/normalizer/requirements.lock
|
|
40
|
+
- name: Qualify actual sandbox and every ingress
|
|
41
|
+
run: bash scripts/qualify_normalizer.sh "$NORMALIZER_TEST_IMAGE"
|
|
42
|
+
- name: Deterministic normalization property corpus
|
|
43
|
+
run: pytest -q tests/fuzz/test_fuzz_normalization.py --hypothesis-seed=0
|
|
@@ -30,6 +30,28 @@ Streamable HTTP; the v0.3 `guard` proxy adds deterministic runtime *result* insp
|
|
|
30
30
|
|
|
31
31
|
## [Unreleased]
|
|
32
32
|
|
|
33
|
+
## [2.3.0] — 2026-11-14
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- DSE-718 opt-in Linux supplied-content normalization: independent isolated parser
|
|
38
|
+
worker; all nine ingress kinds; bounded text/web/data, MIME, ZIP and conservative
|
|
39
|
+
text-PDF extraction; raw and normalized inspection, labeled provenance, immutable
|
|
40
|
+
worker IDs, atomic guard/offline refusal, `normalize` evidence CLI and dedicated
|
|
41
|
+
real-sandbox qualification. Office/OCR, external retrieval and non-Linux worker
|
|
42
|
+
execution are unsupported. No whole-ATK or arbitrary-format claim is made.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- Both dependency locks pin `opentelemetry-api` 1.45.2 to address
|
|
47
|
+
GHSA-mf5v-w3w3-f6cg (quadratic-time traceparent parsing).
|
|
48
|
+
- `auth audit` accepts 26-character lowercase alphanumeric 1Password vault/item
|
|
49
|
+
IDs in exact `op://vault/item/field` references. Field and fragment token checks
|
|
50
|
+
and checks for other URI schemes and filesystem paths remain in force (DSE-2124).
|
|
51
|
+
- `check` no longer passes when `overall_digest` differs but no per-entry drift fires
|
|
52
|
+
(e.g. a baseline lock with duplicate tool/resource/prompt keys): it now reports
|
|
53
|
+
`digest-mismatch-unexplained` (high) and exits non-zero (DSE-2125).
|
|
54
|
+
|
|
33
55
|
## [2.2.0] — 2026-10-24
|
|
34
56
|
|
|
35
57
|
### Community corpus layout (DSE-2143)
|
|
@@ -571,7 +593,8 @@ v1-strong foundation. Highlights of the 0.3.0 → 1.0.0 arc:
|
|
|
571
593
|
declared surface, RFC 8785 (JCS) + SHA-256 canonicalization, SARIF output, and a live
|
|
572
594
|
integrity-gate workflow with committed `clean.warden.lock`.
|
|
573
595
|
|
|
574
|
-
[Unreleased]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v2.
|
|
596
|
+
[Unreleased]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v2.3.0...HEAD
|
|
597
|
+
[2.3.0]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v2.2.0...v2.3.0
|
|
575
598
|
[2.2.0]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v2.1.0...v2.2.0
|
|
576
599
|
[2.1.0]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v2.0.0...v2.1.0
|
|
577
600
|
[1.1.0]: https://github.com/DataScience-EngineeringExperts/mcp-warden/compare/v1.0.1...v1.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Documentation Index — mcp-warden
|
|
2
2
|
|
|
3
|
-
Last Updated: 2026-
|
|
3
|
+
Last Updated: 2026-11-14
|
|
4
4
|
|
|
5
5
|
Master index of every document in this repository. The `docs/` files are the
|
|
6
6
|
**security contract and source of truth** for all algorithms; the three core docs
|
|
@@ -12,7 +12,7 @@ describe and visualize the implementation that satisfies that contract.
|
|
|
12
12
|
|
|
13
13
|
| # | Doc | Purpose |
|
|
14
14
|
|---|-----|---------|
|
|
15
|
-
| 1 | [`README.md`](README.md) | Project overview, install, the pin/check CI demo (full walkthrough
|
|
15
|
+
| 1 | [`README.md`](README.md) | Project overview, install, the pin/check CI demo (full walkthrough in [`docs/PIN_CHECK_DEMO.md`](docs/PIN_CHECK_DEMO.md)), CLI reference (incl. v0.3 `lock rotate`, DSE-1530 `lock sign`, DSE-1539 `--max-pages` + redacted offline `diff` viewer), GitHub Action usage section (Issue #18), **pre-commit hook section (Issue #22)** |
|
|
16
16
|
| 2 | [`SYSTEM_CONTEXT_DIAGRAM.md`](SYSTEM_CONTEXT_DIAGRAM.md) | System context + pin/check sequence (mermaid); trust boundary; `conclave` as dev-time reviewer only; composite GitHub Action + **pre-commit hook** as consumer delivery vehicles |
|
|
17
17
|
| 3 | [`DOCUMENTATION_INDEX.md`](DOCUMENTATION_INDEX.md) | This file |
|
|
18
18
|
|
|
@@ -34,6 +34,22 @@ implementations (Python reference, zero-dependency TypeScript) prove it in CI.
|
|
|
34
34
|
| [`packages/lock-ts/`](packages/lock-ts/README.md) | `@mcp-warden/lock` — verify-only TypeScript: hand-written JCS, SHA-256, capability + skeleton derivation, drift classifier; `npm test` runs the same corpus |
|
|
35
35
|
| [`.github/workflows/integrity-gate.yml`](.github/workflows/integrity-gate.yml) `conformance` job | Runs both harnesses; mutation proof flips one hex char and requires BOTH to fail |
|
|
36
36
|
|
|
37
|
+
## Supplied-content normalization (DSE-718)
|
|
38
|
+
|
|
39
|
+
| Artifact | Purpose |
|
|
40
|
+
|---|---|
|
|
41
|
+
| [`docs/CONTENT_NORMALIZATION.md`](docs/CONTENT_NORMALIZATION.md) | Finite nine-ingress supplied-content contract, format/provenance limits, Linux sandbox, budgets, refusal/migration and qualification |
|
|
42
|
+
| [`components/normalizer/README.md`](components/normalizer/README.md) | Standalone parser component, independent hash lock, pinned runtime and conservative format profiles |
|
|
43
|
+
| [`src/mcp_warden/normalization_models.py`](src/mcp_warden/normalization_models.py) | Frozen finite profiles and evidence types |
|
|
44
|
+
| [`src/mcp_warden/normalization.py`](src/mcp_warden/normalization.py) | Trusted coordinator validates worker evidence and derives untrusted envelopes |
|
|
45
|
+
| [`src/mcp_warden/normalization_sandbox.py`](src/mcp_warden/normalization_sandbox.py) | Fixed immutable-image Linux Docker supervisor; bounded IPC and fail-closed cleanup |
|
|
46
|
+
| [`src/mcp_warden/normalization_ingress.py`](src/mcp_warden/normalization_ingress.py) | All nine supplied-payload adapters; no external retrieval |
|
|
47
|
+
| [`src/mcp_warden/normalization_inspection.py`](src/mcp_warden/normalization_inspection.py) | Raw/normalized shared catalog and supplied MCP container checks |
|
|
48
|
+
| [`src/mcp_warden/normalization_guard.py`](src/mcp_warden/normalization_guard.py) | Atomic opt-in live frame mediation before legacy handling |
|
|
49
|
+
| [`src/mcp_warden/normalization_trace.py`](src/mcp_warden/normalization_trace.py) | Bounded, explicit-direction offline trace loading |
|
|
50
|
+
| [`scripts/qualify_normalizer.sh`](scripts/qualify_normalizer.sh) | Actual-image qualification with independent builder QA claims |
|
|
51
|
+
| [`.github/workflows/normalization.yml`](.github/workflows/normalization.yml) | Dedicated Python 3.12 Linux parser/sandbox/every-ingress/fuzz qualification |
|
|
52
|
+
|
|
37
53
|
## Agent gates (`deploy-gate` + `auth audit` — DSE-1257 / DSE-1258)
|
|
38
54
|
|
|
39
55
|
Two fail-closed gates extending warden past MCP-surface integrity into the adjacent
|
|
@@ -47,10 +63,11 @@ is the MCP auth posture sound. Both reuse the `check` exit-code contract (0 clea
|
|
|
47
63
|
| [`src/mcp_warden/deploy_gate.py`](src/mcp_warden/deploy_gate.py) | `WRD-GATE-*` engine: eval thresholds, guardrail presence, budget, approval receipt |
|
|
48
64
|
| [`src/mcp_warden/cli_deploy_gate.py`](src/mcp_warden/cli_deploy_gate.py) | `deploy-gate` command body (register idiom) |
|
|
49
65
|
| [`src/mcp_warden/auth_audit.py`](src/mcp_warden/auth_audit.py) | `WRD-AUTH-*` static config audit; reuses `checks_secret.scan_field` for vendor patterns (vendor hits are never downgraded); template fill-me-ins are `WRD-AUTH-PLACEHOLDER-SECRET` (low), matched on whole tokens |
|
|
50
|
-
| [`src/mcp_warden/auth_refs.py`](src/mcp_warden/auth_refs.py) | Reference / locator / placeholder heuristics behind `WRD-AUTH-*`: `${VAR}` forms, secret-manager URIs and credential paths, token-shaped segments (incl. `-`/`_`-joined tokens, DSE-1540), placeholder bounds |
|
|
66
|
+
| [`src/mcp_warden/auth_refs.py`](src/mcp_warden/auth_refs.py) | Reference / locator / placeholder heuristics behind `WRD-AUTH-*`: `${VAR}` forms, secret-manager URIs and credential paths, token-shaped segments (incl. `-`/`_`-joined tokens, DSE-1540), position-scoped 1Password IDs (DSE-2124), placeholder bounds |
|
|
51
67
|
| [`src/mcp_warden/cli_auth.py`](src/mcp_warden/cli_auth.py) | `auth audit` sub-app command body |
|
|
52
68
|
| [`tests/test_deploy_gate.py`](tests/test_deploy_gate.py) | Engine per-control pass/fail + CLI exit codes + fail-closed on malformed evidence |
|
|
53
69
|
| [`tests/test_auth_audit.py`](tests/test_auth_audit.py) | Every rule, the deliberate non-flags (loopback, `${VAR}` refs, stdio), redaction, CLI/JSON/SARIF |
|
|
70
|
+
| [`tests/test_auth_refs_op_ids.py`](tests/test_auth_refs_op_ids.py) | 1Password ID references and field, fragment, scheme, length, case and malformed-path regression controls (DSE-2124) |
|
|
54
71
|
| [`tests/test_agent_gates_examples.py`](tests/test_agent_gates_examples.py) | Pins the shipped examples to the per-server verdicts their README claims, so a rule change cannot silently make the docs wrong; also asserts the planted fake credentials never reach a finding field |
|
|
55
72
|
| [`examples/agent-gates/`](examples/agent-gates/) | Runnable demos — a 6-server config (4 flagged / 2 deliberately clean, incl. the `Bearer ${VAR}` embedded-reference shape from #94) and pass/fail deploy evidence, with expected verdicts documented and verified |
|
|
56
73
|
|
|
@@ -306,3 +323,9 @@ review/signature CLI. Tests are `tests/test_artifact_trust.py`,
|
|
|
306
323
|
| `tests/fixtures/poison_server.py` | **(v0.2)** result-poisoning fixture server (ANSI/secret-echo/exfil/inject/clean tools) |
|
|
307
324
|
| `tests/fixtures/crash_server.py` · `listchange_server.py` · `clean_listchange.warden.lock` | **(v0.3)** raw-stdio lifecycle fixtures: crash-mid-call (`-32002`) and `tools/list_changed` rug-pull + its pinned clean lock |
|
|
308
325
|
| `tests/fixtures/fault_guard_launcher.py` | **(#21)** test-only launcher that monkeypatches ONE inspection function (`inspect_result` / `evaluate_call` / `diverges_from_lock` / `_hash_live_tools`) to raise inside the spawned guard child, then runs the real CLI — drives the `--strict` terminate-site tests without any test branch in production code; `FAULT_SECRET` plants a secret for the redaction test |
|
|
326
|
+
|
|
327
|
+
## Version history
|
|
328
|
+
|
|
329
|
+
| Date | Change |
|
|
330
|
+
|------|--------|
|
|
331
|
+
| 2026-11-06 | Recorded TheDataExperts PyPI ownership, Active organization billing, normal company publisher and removal of the obsolete personal publisher; linked successful authentication-only run 42224199909. Account-wide token revoked; project-only manual fallback retained. No upload today; 2.2.0 unchanged and next normal release upload/provenance proof outstanding. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcp-warden-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: CI-first MCP supply-chain integrity gate: pin and verify the declared tool/resource/prompt surface of an MCP server, plus runtime tool-result inspection (guard/inspect).
|
|
5
5
|
Project-URL: Homepage, https://github.com/DataScience-EngineeringExperts/mcp-warden
|
|
6
6
|
Project-URL: Repository, https://github.com/DataScience-EngineeringExperts/mcp-warden
|
|
@@ -34,7 +34,7 @@ Description-Content-Type: text/markdown
|
|
|
34
34
|
|
|
35
35
|
# mcp-warden
|
|
36
36
|
|
|
37
|
-
Last Updated: 2026-
|
|
37
|
+
Last Updated: 2026-11-14
|
|
38
38
|
|
|
39
39
|
[](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml)
|
|
40
40
|
[](LICENSE)
|
|
@@ -53,6 +53,11 @@ Older locks stay readable, but require review and re-pinning for this coverage.
|
|
|
53
53
|
Hints are server claims, not proof of safety, and schemas do not certify content. Release
|
|
54
54
|
operators can check production OIDC without uploading via [`RELEASING.md`](RELEASING.md).
|
|
55
55
|
|
|
56
|
+
`mcp-warden-cli` is owned by the [TheDataExperts PyPI organization](https://pypi.org/org/TheDataExperts/).
|
|
57
|
+
The company-repository publisher passed an authentication-only check on 2026-11-06;
|
|
58
|
+
that check uploaded no package. The next normal release must prove OIDC upload
|
|
59
|
+
and provenance; see the [publishing status](RELEASING.md#ownership-and-publishing-status--2026-11-06).
|
|
60
|
+
|
|
56
61
|
The proposed next direction is a protocol-neutral **Warden**: human-approved tool versions and bounded actions, with untrusted inputs kept separate from authority.
|
|
57
62
|
The [upgrade plan and checkpoint proposal](docs/plans/2026-10-02-tool-integrity-upgrade.md)
|
|
58
63
|
maps prompts, retrieval, code execution, and serverless adapters to existing Agent
|
|
@@ -212,6 +217,21 @@ automatically — so the use cases are sequenced by leverage:
|
|
|
212
217
|
- **Agent-framework integrator** *(post-launch).* Enforce that only warden-locked servers
|
|
213
218
|
register in a LangGraph-style orchestrator — one integration locks an entire downstream ecosystem.
|
|
214
219
|
|
|
220
|
+
### Isolated supplied-content inspection (DSE-718)
|
|
221
|
+
|
|
222
|
+
The opt-in Linux normalizer processes supplied text/web/data, email, ZIP and a
|
|
223
|
+
conservative text-PDF subset through one engine across all nine declared ingress
|
|
224
|
+
families. A separately hash-locked parser image runs without network, credentials
|
|
225
|
+
or host-data mounts. The coordinator preserves raw-byte evidence and creates
|
|
226
|
+
untrusted derived envelopes with labeled source precision; it grants no delivery
|
|
227
|
+
authority. Office/OCR, external retrieval and non-Linux worker execution refuse.
|
|
228
|
+
|
|
229
|
+
`normalize <file> --media-type <MIME> --source-kind <kind> --normalizer-image <sha256:id>`
|
|
230
|
+
emits evidence and redacted findings. `guard` and `inspect` accept the same
|
|
231
|
+
`--normalizer-image` option for atomic, fail-closed inspection using a qualified
|
|
232
|
+
immutable local image. Without it, their narrower legacy contracts remain.
|
|
233
|
+
See [the supported profiles, sandbox qualification and limits](docs/CONTENT_NORMALIZATION.md).
|
|
234
|
+
|
|
215
235
|
---
|
|
216
236
|
|
|
217
237
|
## What it does
|
|
@@ -424,6 +444,7 @@ run the gate only on push:
|
|
|
424
444
|
| `mcp-warden policy eval <file> <sample.json> [--lock F]` | Evaluate one sample call | **non-zero on a deny verdict** (CI assertion) |
|
|
425
445
|
| `mcp-warden guard <server-cmd...> [--lock F] [--policy F] [--no-block-* / --allow-exfil-domain] [--block-inject-phrase] [--audit-only] [--strict] [--sarif F] [--record T]` | **(v0.3)** Transparent stdio proxy: inspects `tools/call` results + arguments at runtime. **Deterministic tier blocks by default**; opt out per-category with `--no-block-<category>` or fully with `--audit-only`. `--strict` fails CLOSED on an internal inspection error (exit `3`) | child's exit code; `3` on a `--strict` abort; otherwise never breaks the session |
|
|
426
446
|
| `mcp-warden inspect <trace.jsonl> [--lock F] [--sarif F]` | **(v0.2)** Offline analyzer over a recorded JSON-RPC session — same `WRD-RES-*` catalog as `guard` (always report-only) | non-zero on any BLOCK-tier finding; 2 on read error |
|
|
447
|
+
| `mcp-warden normalize <file> --media-type MIME --source-kind KIND --normalizer-image sha256:ID` | Linux supplied-content normalization/inspection through an independently qualified isolated worker; emits evidence, not extracted content. `guard`/`inspect` also accept `--normalizer-image`; see [`docs/CONTENT_NORMALIZATION.md`](docs/CONTENT_NORMALIZATION.md) | 0 no blocking finding; 1 blocking finding; 2 refusal/error |
|
|
427
448
|
| `mcp-warden lock rotate <lock> [--approver ID] [--actor ID] [--note T] [--json]` | **(v0.3)** Re-attest provenance on an existing baseline without re-capturing the surface; `overall_digest` stays **byte-identical** (WARDEN_LOCK_SCHEMA §8.2). Fails closed on a tampered/inconsistent lock | 0 on success, 2 on missing/invalid/tampered lock |
|
|
428
449
|
| `mcp-warden lock sign <lock> [--coordinate C] [--identity-token T]` | **(DSE-1530)** Sigstore-sign an existing **unsigned** lock and write `<lockname>.sigstore` beside it — for attesters that capture offline and sign afterwards. v2 statement (binds the coordinate) with `--coordinate`, v1 otherwise; `overall_digest` unchanged. Refuses an existing sidecar or an already-signed lock | 0 on success; **1 on signing failure (fail closed, no partial sidecar)**; 2 on missing/tampered lock, bad coordinate, existing signature, or missing `mcp-warden[sigstore]` |
|
|
429
450
|
| `mcp-warden diff <lock-a> <lock-b> [--json] [--sarif F] [--no-provenance] [--exit-code]` | **(v0.3)** Offline, **redacted** viewer over the drift engine: renders integrity drift between two existing locks (A=baseline, B=current) + a separate informational provenance section. Never re-captures and never prints raw `server.command`/`args` (secret-safe) | 0 (viewer); with `--exit-code`, 1 on **integrity** drift only; 2 on missing/invalid lock |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mcp-warden
|
|
2
2
|
|
|
3
|
-
Last Updated: 2026-
|
|
3
|
+
Last Updated: 2026-11-14
|
|
4
4
|
|
|
5
5
|
[](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml)
|
|
6
6
|
[](LICENSE)
|
|
@@ -19,6 +19,11 @@ Older locks stay readable, but require review and re-pinning for this coverage.
|
|
|
19
19
|
Hints are server claims, not proof of safety, and schemas do not certify content. Release
|
|
20
20
|
operators can check production OIDC without uploading via [`RELEASING.md`](RELEASING.md).
|
|
21
21
|
|
|
22
|
+
`mcp-warden-cli` is owned by the [TheDataExperts PyPI organization](https://pypi.org/org/TheDataExperts/).
|
|
23
|
+
The company-repository publisher passed an authentication-only check on 2026-11-06;
|
|
24
|
+
that check uploaded no package. The next normal release must prove OIDC upload
|
|
25
|
+
and provenance; see the [publishing status](RELEASING.md#ownership-and-publishing-status--2026-11-06).
|
|
26
|
+
|
|
22
27
|
The proposed next direction is a protocol-neutral **Warden**: human-approved tool versions and bounded actions, with untrusted inputs kept separate from authority.
|
|
23
28
|
The [upgrade plan and checkpoint proposal](docs/plans/2026-10-02-tool-integrity-upgrade.md)
|
|
24
29
|
maps prompts, retrieval, code execution, and serverless adapters to existing Agent
|
|
@@ -178,6 +183,21 @@ automatically — so the use cases are sequenced by leverage:
|
|
|
178
183
|
- **Agent-framework integrator** *(post-launch).* Enforce that only warden-locked servers
|
|
179
184
|
register in a LangGraph-style orchestrator — one integration locks an entire downstream ecosystem.
|
|
180
185
|
|
|
186
|
+
### Isolated supplied-content inspection (DSE-718)
|
|
187
|
+
|
|
188
|
+
The opt-in Linux normalizer processes supplied text/web/data, email, ZIP and a
|
|
189
|
+
conservative text-PDF subset through one engine across all nine declared ingress
|
|
190
|
+
families. A separately hash-locked parser image runs without network, credentials
|
|
191
|
+
or host-data mounts. The coordinator preserves raw-byte evidence and creates
|
|
192
|
+
untrusted derived envelopes with labeled source precision; it grants no delivery
|
|
193
|
+
authority. Office/OCR, external retrieval and non-Linux worker execution refuse.
|
|
194
|
+
|
|
195
|
+
`normalize <file> --media-type <MIME> --source-kind <kind> --normalizer-image <sha256:id>`
|
|
196
|
+
emits evidence and redacted findings. `guard` and `inspect` accept the same
|
|
197
|
+
`--normalizer-image` option for atomic, fail-closed inspection using a qualified
|
|
198
|
+
immutable local image. Without it, their narrower legacy contracts remain.
|
|
199
|
+
See [the supported profiles, sandbox qualification and limits](docs/CONTENT_NORMALIZATION.md).
|
|
200
|
+
|
|
181
201
|
---
|
|
182
202
|
|
|
183
203
|
## What it does
|
|
@@ -390,6 +410,7 @@ run the gate only on push:
|
|
|
390
410
|
| `mcp-warden policy eval <file> <sample.json> [--lock F]` | Evaluate one sample call | **non-zero on a deny verdict** (CI assertion) |
|
|
391
411
|
| `mcp-warden guard <server-cmd...> [--lock F] [--policy F] [--no-block-* / --allow-exfil-domain] [--block-inject-phrase] [--audit-only] [--strict] [--sarif F] [--record T]` | **(v0.3)** Transparent stdio proxy: inspects `tools/call` results + arguments at runtime. **Deterministic tier blocks by default**; opt out per-category with `--no-block-<category>` or fully with `--audit-only`. `--strict` fails CLOSED on an internal inspection error (exit `3`) | child's exit code; `3` on a `--strict` abort; otherwise never breaks the session |
|
|
392
412
|
| `mcp-warden inspect <trace.jsonl> [--lock F] [--sarif F]` | **(v0.2)** Offline analyzer over a recorded JSON-RPC session — same `WRD-RES-*` catalog as `guard` (always report-only) | non-zero on any BLOCK-tier finding; 2 on read error |
|
|
413
|
+
| `mcp-warden normalize <file> --media-type MIME --source-kind KIND --normalizer-image sha256:ID` | Linux supplied-content normalization/inspection through an independently qualified isolated worker; emits evidence, not extracted content. `guard`/`inspect` also accept `--normalizer-image`; see [`docs/CONTENT_NORMALIZATION.md`](docs/CONTENT_NORMALIZATION.md) | 0 no blocking finding; 1 blocking finding; 2 refusal/error |
|
|
393
414
|
| `mcp-warden lock rotate <lock> [--approver ID] [--actor ID] [--note T] [--json]` | **(v0.3)** Re-attest provenance on an existing baseline without re-capturing the surface; `overall_digest` stays **byte-identical** (WARDEN_LOCK_SCHEMA §8.2). Fails closed on a tampered/inconsistent lock | 0 on success, 2 on missing/invalid/tampered lock |
|
|
394
415
|
| `mcp-warden lock sign <lock> [--coordinate C] [--identity-token T]` | **(DSE-1530)** Sigstore-sign an existing **unsigned** lock and write `<lockname>.sigstore` beside it — for attesters that capture offline and sign afterwards. v2 statement (binds the coordinate) with `--coordinate`, v1 otherwise; `overall_digest` unchanged. Refuses an existing sidecar or an already-signed lock | 0 on success; **1 on signing failure (fail closed, no partial sidecar)**; 2 on missing/tampered lock, bad coordinate, existing signature, or missing `mcp-warden[sigstore]` |
|
|
395
416
|
| `mcp-warden diff <lock-a> <lock-b> [--json] [--sarif F] [--no-provenance] [--exit-code]` | **(v0.3)** Offline, **redacted** viewer over the drift engine: renders integrity drift between two existing locks (A=baseline, B=current) + a separate informational provenance section. Never re-captures and never prints raw `server.command`/`args` (secret-safe) | 0 (viewer); with `--exit-code`, 1 on **integrity** drift only; 2 on missing/invalid lock |
|
|
@@ -50,6 +50,28 @@ The workflow uses **OIDC Trusted Publishing**, without a stored GitHub upload to
|
|
|
50
50
|
The repo variable `PYPI_TRUSTED_PUBLISHER=true` permits an attempt; it does not prove
|
|
51
51
|
that a matching PyPI publisher exists. Verify the exchange before cutting a new release.
|
|
52
52
|
|
|
53
|
+
### Ownership and publishing status — 2026-11-06
|
|
54
|
+
|
|
55
|
+
Both `conclave-cli` and `mcp-warden-cli` now belong to the
|
|
56
|
+
[TheDataExperts PyPI organization](https://pypi.org/org/TheDataExperts/),
|
|
57
|
+
transferred from `z3usalmighte` direct ownership. Organization billing is Active;
|
|
58
|
+
Ernest (`z3usalmighte`) remains its sole human owner. Both projects have a normal
|
|
59
|
+
Trusted Publisher for their respective `DataScience-EngineeringExperts` repository,
|
|
60
|
+
`release.yml`, with a blank environment matching the workflows. No pending
|
|
61
|
+
publishers remain in the inspected account.
|
|
62
|
+
|
|
63
|
+
The company-repository publisher was registered before the obsolete
|
|
64
|
+
`ernestprovo23` publisher was removed. [Verification run 42224199909](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/runs/42224199909)
|
|
65
|
+
succeeded at `42e08c505eb28f82b01d3fa81a7696c56f6e6383`: PyPI accepted the OIDC
|
|
66
|
+
exchange; build, signing and upload jobs were skipped. This establishes authentication,
|
|
67
|
+
not project upload permission or successful release publication.
|
|
68
|
+
|
|
69
|
+
The account-wide upload token was revoked. A `mcp-warden-cli`-only manual fallback
|
|
70
|
+
is retained pending the next normal release's successful OIDC upload and provenance
|
|
71
|
+
verification. It is not a workflow fallback. No upload or release was performed on
|
|
72
|
+
2026-11-06; the published version remains **2.2.0**. Keep the next-release proof
|
|
73
|
+
outstanding until section 2 confirms the new version and attestations.
|
|
74
|
+
|
|
53
75
|
### New projects only — pending publisher
|
|
54
76
|
|
|
55
77
|
1. Log in to <https://pypi.org> as the account that will own `mcp-warden-cli`.
|
|
@@ -160,17 +182,11 @@ The same exchange error occurred on the prior 1.2.0 release. The authorized manu
|
|
|
160
182
|
[PyPI 2.0.0](https://pypi.org/project/mcp-warden-cli/2.0.0/). That recovery proves
|
|
161
183
|
publication, not that OIDC automation was repaired.
|
|
162
184
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Do not rebuild/re-sign/replace the released assets as a repair attempt. If the
|
|
171
|
-
original artifacts expired, stop and plan a fix-forward release. Success means
|
|
172
|
-
OIDC authentication passes and the existing immutable files are handled by
|
|
173
|
-
`skip-existing`; verify the public wheel/sdist hashes remain unchanged.
|
|
185
|
+
The 2026-11-06 authentication-only check above supersedes the earlier unknown
|
|
186
|
+
publisher-alignment status. The old 2.0.0 run is historical evidence, not the next
|
|
187
|
+
verification target. Do not rebuild, re-sign, re-upload or rerun that release as
|
|
188
|
+
part of this closeout. Prove end-to-end OIDC upload on the next normal release,
|
|
189
|
+
then verify its new PyPI files and provenance under section 2.
|
|
174
190
|
|
|
175
191
|
### (Optional) TestPyPI dry-run publisher
|
|
176
192
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# mcp-warden — System Context Diagram
|
|
2
2
|
|
|
3
|
-
Last Updated: 2026-
|
|
3
|
+
Last Updated: 2026-11-14
|
|
4
4
|
|
|
5
|
-
**CLI 2.
|
|
5
|
+
**CLI 2.3.0 / schema level 4** includes complete tool annotations and output
|
|
6
6
|
schemas, with structural output drift and Python/TypeScript parity. The existing
|
|
7
7
|
tools/list gate compares those commitments for v4 locks; legacy locks retain narrower
|
|
8
8
|
runtime coverage and require re-pin for the new fields. Annotations grant no authority.
|
|
@@ -60,6 +60,27 @@ logic) plus a separate informational provenance section. It never prints raw
|
|
|
60
60
|
> enter an existing code-scanning pipeline with no new plumbing. Runtime capability
|
|
61
61
|
> brokering remains out of scope (DSE-725). See [`docs/AGENT_GATES.md`](docs/AGENT_GATES.md).
|
|
62
62
|
|
|
63
|
+
> **Supplied-content normalization (DSE-718)** is an opt-in Linux worker path,
|
|
64
|
+
> separate from the base CLI parser dependencies. All nine input families use
|
|
65
|
+
> the same engine over supplied bytes; no external connectors fetch content.
|
|
66
|
+
> The coordinator creates digest-bound untrusted lineage/maps and validates
|
|
67
|
+
> bounded output; PDP/PEP remains the delivery authority. The optional guard
|
|
68
|
+
> wrapper inspects every complete server frame before legacy delivery, forces
|
|
69
|
+
> strict refusal, and has no in-process fallback. See
|
|
70
|
+
> [`docs/CONTENT_NORMALIZATION.md`](docs/CONTENT_NORMALIZATION.md).
|
|
71
|
+
|
|
72
|
+
```mermaid
|
|
73
|
+
flowchart LR
|
|
74
|
+
supplied[Supplied bytes: nine ingress families] --> capture[Exact-byte ingress envelope]
|
|
75
|
+
capture --> coord[normalization.py: trusted evidence coordinator]
|
|
76
|
+
coord --> sandbox[normalization_sandbox.py: Linux isolated immutable worker]
|
|
77
|
+
sandbox --> parser[components/normalizer: bounded recursive parsers]
|
|
78
|
+
parser --> validate[Bounded untrusted manifest validation]
|
|
79
|
+
validate --> evidence[Derived untrusted envelope and source-map digest]
|
|
80
|
+
evidence --> inspection[Raw and normalized shared inspection]
|
|
81
|
+
inspection --> gate[Existing policy and delivery boundary]
|
|
82
|
+
```
|
|
83
|
+
|
|
63
84
|
> **`doctor` (DSE-1516)** is the zero-config entry point and sits at the far left of the
|
|
64
85
|
> picture: it reads the MCP client configs already on the developer's machine (Claude
|
|
65
86
|
> Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex — a documented, closed set with a
|
|
@@ -101,7 +122,11 @@ logic) plus a separate informational provenance section. It never prints raw
|
|
|
101
122
|
> Minting can change PyPI pending-publisher records; it is not universally read-only.
|
|
102
123
|
> Successful exchange is not proof of project upload permission. CLI 2.0.0's
|
|
103
124
|
> failed OIDC exchange was recovered with an authorized manual upload of the signed bytes;
|
|
104
|
-
>
|
|
125
|
+
> the company-repository publisher subsequently passed the 2026-11-06
|
|
126
|
+
> authentication-only check ([run 42224199909](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/runs/42224199909)).
|
|
127
|
+
> `mcp-warden-cli` now belongs to the [TheDataExperts PyPI organization](https://pypi.org/org/TheDataExperts/).
|
|
128
|
+
> That authentication-only check uploaded no package. End-to-end OIDC upload
|
|
129
|
+
> and provenance require proof from the next normal release. See [`RELEASING.md`](RELEASING.md).
|
|
105
130
|
|
|
106
131
|
---
|
|
107
132
|
|
|
@@ -231,9 +231,9 @@ mdurl==0.1.2 \
|
|
|
231
231
|
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
|
|
232
232
|
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
|
|
233
233
|
# via markdown-it-py
|
|
234
|
-
opentelemetry-api==1.45.
|
|
235
|
-
--hash=sha256:
|
|
236
|
-
--hash=sha256:
|
|
234
|
+
opentelemetry-api==1.45.2 \
|
|
235
|
+
--hash=sha256:2cbd737377e710ee740d261c94e93fa0f08e6d037c18f17513cc0a2d94479a34 \
|
|
236
|
+
--hash=sha256:d7b0008e21e5fd61cbe7a7f34ca3b6905a78ab677d9bc395e299359c75cda6b4
|
|
237
237
|
# via mcp
|
|
238
238
|
pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' \
|
|
239
239
|
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Official Python 3.12.16 slim-bookworm linux/amd64 manifest, reviewed 2026-11-14.
|
|
2
|
+
FROM python:3.12.16-slim-bookworm@sha256:0f086103b026048cc50cb5da25ec435c023c5241a83fc44daea593377abc61c4
|
|
3
|
+
|
|
4
|
+
COPY components/normalizer/requirements.lock /worker/requirements.lock
|
|
5
|
+
RUN python -m pip install --no-cache-dir --no-compile --require-hashes \
|
|
6
|
+
--only-binary=:all: --no-deps -r /worker/requirements.lock
|
|
7
|
+
COPY components/normalizer/*.py /worker/
|
|
8
|
+
COPY src/mcp_warden/normalization_ipc.py /worker/normalization_ipc.py
|
|
9
|
+
COPY LICENSE /worker/LICENSE
|
|
10
|
+
COPY components/normalizer/THIRD_PARTY_NOTICES.md /worker/THIRD_PARTY_NOTICES.md
|
|
11
|
+
WORKDIR /worker
|
|
12
|
+
USER 10001:10001
|
|
13
|
+
ENTRYPOINT ["/usr/bin/env", "-i", "/usr/local/bin/python3", "-I", "-B", "/worker/worker.py"]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Isolated normalization parser
|
|
2
|
+
|
|
3
|
+
This component is a one-request, supplied-content worker. It does not retrieve
|
|
4
|
+
URLs, use credentials, write files, grant delivery authority, or provide an
|
|
5
|
+
in-process fallback. The trusted coordinator must validate its entire output.
|
|
6
|
+
The Dockerfile and supervisor provide the separately qualified Linux isolation
|
|
7
|
+
boundary; importing this worker directly is only a parser test seam.
|
|
8
|
+
|
|
9
|
+
Runtime identity is Python 3.12, Unicode 15.0.0 and the parser closure
|
|
10
|
+
`pypdf==7.1.0;markdown-it-py==4.3.0;mdurl==0.1.2`. Every request checks all
|
|
11
|
+
installed package versions. `requirements.lock` independently hash-locks all
|
|
12
|
+
three third-party wheels.
|
|
13
|
+
Install with `pip install --require-hashes --only-binary=:all: -r requirements.lock`.
|
|
14
|
+
The immutable image contains `worker.py`, `formats*.py`, and the coordinator's
|
|
15
|
+
standalone `normalization_ipc.py` under `/worker`. The entrypoint adds only its
|
|
16
|
+
immutable own directory to Python's isolated-mode import path.
|
|
17
|
+
|
|
18
|
+
The framed protocol accepts exactly one root and emits exactly one success or
|
|
19
|
+
input-free `NRM-*` refusal. Frames and aggregate wire bytes are bounded by the
|
|
20
|
+
shared IPC module. Nothing is delivered until the full root succeeds.
|
|
21
|
+
|
|
22
|
+
Supported formats are strict UTF-8 plain text/Markdown, JSON, XML, HTML, CSV,
|
|
23
|
+
RFC822/MIME, ZIP and conservative text PDF. MIME can explicitly declare ASCII,
|
|
24
|
+
UTF-8 or ISO-8859-1. ZIP members require a supported suffix or PDF/ZIP signature;
|
|
25
|
+
conflicting signatures, traversal, duplicate names, directories, links,
|
|
26
|
+
encryption, unsupported compression/extra fields/descriptors, unknown members and empty
|
|
27
|
+
entries refuse.
|
|
28
|
+
Only stored/DEFLATE ZIP compression is supported; all traversal remains in memory.
|
|
29
|
+
MIME decodes strict base64/quoted-printable and traverses supported attachments.
|
|
30
|
+
Every MIME part rejects duplicate Content-Type, Content-Transfer-Encoding,
|
|
31
|
+
Content-Disposition or MIME-Version headers, including case variants; no
|
|
32
|
+
first-header interpretation of those ambiguous inputs is accepted.
|
|
33
|
+
JSON rejects duplicate keys/nonfinite constants and recursively inspects supplied
|
|
34
|
+
MCP `{mimeType, blob|data|text}` carriers, while retaining their encoded source
|
|
35
|
+
and all surrounding keys/metadata. XML rejects DTD/entities. HTML retains hidden
|
|
36
|
+
content, attributes, comments and an entity-decoded syntax view; non-void tags
|
|
37
|
+
require explicit balanced closing tags under this conservative profile. CSV includes all
|
|
38
|
+
fields. Source syntax is retained alongside structured decoded inspection views.
|
|
39
|
+
Markdown uses markdown-it-py's CommonMark preset without plugins or rendering.
|
|
40
|
+
Decoded text/code tokens, link/image attributes, fence info, unused/duplicate
|
|
41
|
+
reference definitions, and embedded HTML/comment/attribute evidence are all
|
|
42
|
+
inspected. Code tokens retain CommonMark's literal escape semantics. A dedicated
|
|
43
|
+
combined decoded token view reconstructs instructions split across emphasis,
|
|
44
|
+
links or embedded HTML tags. Unknown tokens and unbalanced embedded HTML refuse;
|
|
45
|
+
the parser's internal nesting cap exceeds the worker's rejecting depth limit so
|
|
46
|
+
it cannot silently discard a deep tail before an ancestor triggers refusal.
|
|
47
|
+
HTML and XML also concatenate decoded character data across tags into a dedicated
|
|
48
|
+
inspection segment. JSON adds a depth-first, input-order string-value concatenation
|
|
49
|
+
view without inserting keys between values. These additional views reconstruct
|
|
50
|
+
split text within one supplied root and consume the same output/map/work budgets;
|
|
51
|
+
they do not replace syntax, attribute, comment, key or individual-value evidence.
|
|
52
|
+
|
|
53
|
+
PDF uses strict pypdf parsing and checks every referenced cross-reference object,
|
|
54
|
+
including unreachable objects. It retains textual metadata and UTF-8 decoded
|
|
55
|
+
stream syntax, then extracts page text including invisible text. Only no-filter
|
|
56
|
+
and bounded DEFLATE streams are accepted. Encryption, image/form XObjects,
|
|
57
|
+
embedded fonts, byte strings, object streams, active content, XMP, unsupported
|
|
58
|
+
operators/filters, unknown fonts and empty/unexplained pages refuse. Office, OCR,
|
|
59
|
+
other archives and arbitrary octet streams are outside the profile. This is a
|
|
60
|
+
conservative text-PDF subset; normal PDFs outside it can legitimately refuse.
|
|
61
|
+
|
|
62
|
+
Every nested parser shares one root ledger. `input_bytes` is the root length;
|
|
63
|
+
`expanded_bytes` counts decoded ZIP/MIME/embedded payload and PDF-stream bytes;
|
|
64
|
+
`output_bytes` sums inspection UTF-8 bytes; `nodes`, `members`, `spans`, and `work`
|
|
65
|
+
are cumulative. `work` charges inspected/decoded bytes, traversal nodes and PDF
|
|
66
|
+
operations. `depth` and `combining_run` are high-water marks. `map_bytes` equals
|
|
67
|
+
the canonical JSON full segment-list size, including raw and normalized text.
|
|
68
|
+
Budgets never reset for members, pages or alternate views. Repeated evidence can
|
|
69
|
+
therefore reach the map/output cap before the root input cap.
|
|
70
|
+
|
|
71
|
+
Inspection text applies NFKC then removes Unicode Cf and Cc controls except
|
|
72
|
+
TAB/LF/CR; original extracted text remains in `raw_text` for raw inspection.
|
|
73
|
+
Only unchanged UTF-8 root plain text has exact attribution. All other segments
|
|
74
|
+
use conservative root byte ranges and explicit page/member/view locators.
|
|
75
|
+
Structural completeness describes this finite parser profile, never semantic
|
|
76
|
+
extraction completeness. Parser omissions and dependency compromise remain
|
|
77
|
+
residual risks; worker evidence stays untrusted and cannot remove taint.
|
|
78
|
+
|
|
79
|
+
Parser corpus command (on builder):
|
|
80
|
+
`PYTHONPATH=src .venv/bin/pytest -q tests/test_normalizer_formats.py`.
|
|
81
|
+
Sandbox qualification, coordinator validation, guard parity and final artifact
|
|
82
|
+
identity require their separate integration tests.
|
|
83
|
+
|
|
84
|
+
Dependency review (2026-11-14): official PyPI JSON selected markdown-it-py 4.3.0
|
|
85
|
+
and mdurl 0.1.2; the only non-extra Markdown dependency is `mdurl~=0.1`.
|
|
86
|
+
Both installed wheel license files contain the MIT grant (markdown-it-py also
|
|
87
|
+
includes its upstream markdown-it license). Version-specific PyPI advisory
|
|
88
|
+
lists were empty and exact PyPI/version queries to OSV returned no findings at
|
|
89
|
+
review time. These are point-in-time advisory checks, not proof of absence.
|
|
90
|
+
Sources: https://pypi.org/pypi/markdown-it-py/4.3.0/json ,
|
|
91
|
+
https://pypi.org/pypi/mdurl/0.1.2/json ,
|
|
92
|
+
https://markdown-it-py.readthedocs.io/en/latest/using.html ,
|
|
93
|
+
https://google.github.io/osv.dev/post-v1-query/ .
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Parser image notices
|
|
2
|
+
|
|
3
|
+
MCP-Warden worker and shared framing code are distributed under the MIT license
|
|
4
|
+
copied from this repository to `/worker/LICENSE` in the image.
|
|
5
|
+
|
|
6
|
+
The image installs original hash-verified wheels and retains their bundled
|
|
7
|
+
copyright and license files under Python's `site-packages` distribution metadata:
|
|
8
|
+
|
|
9
|
+
| Distribution | Version | License |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| pypdf | 7.1.0 | BSD-3-Clause |
|
|
12
|
+
| markdown-it-py | 4.3.0 | MIT |
|
|
13
|
+
| mdurl | 0.1.2 | MIT |
|
|
14
|
+
|
|
15
|
+
Keep those original notices with any redistribution. The Python interpreter and
|
|
16
|
+
base operating-system components retain the notices supplied by the pinned
|
|
17
|
+
official Python image. This file identifies dependencies; it does not replace
|
|
18
|
+
their complete license texts.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Root-cumulative semantic budgets and deterministic inspection transforms."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import unicodedata
|
|
5
|
+
|
|
6
|
+
from normalization_ipc import NormalizationError, canonical
|
|
7
|
+
|
|
8
|
+
PROFILE = "mcp-warden.normalizer.v1"
|
|
9
|
+
PARSER_ID = "pypdf==7.1.0;markdown-it-py==4.3.0;mdurl==0.1.2"
|
|
10
|
+
CEILINGS = dict(input_bytes=16*1024*1024, expanded_bytes=64*1024*1024,
|
|
11
|
+
output_bytes=16*1024*1024, depth=8, nodes=4096, members=256,
|
|
12
|
+
spans=100_000, map_bytes=8*1024*1024, combining_run=64, work=100_000_000)
|
|
13
|
+
SUPPORTED = frozenset({"text/plain", "application/json", "application/xml", "text/xml",
|
|
14
|
+
"text/html", "text/markdown", "text/csv", "message/rfc822",
|
|
15
|
+
"application/zip", "application/pdf"})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def fail(code="NRM-MALFORMED"):
|
|
19
|
+
raise NormalizationError(code)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def decode(data, charset="utf-8"):
|
|
23
|
+
if charset.lower().replace("_", "-") not in {"utf-8", "utf8", "us-ascii", "ascii", "iso-8859-1"}:
|
|
24
|
+
fail("NRM-UNSUPPORTED")
|
|
25
|
+
try:
|
|
26
|
+
text = data.decode(charset, errors="strict")
|
|
27
|
+
text.encode("utf-8", errors="strict")
|
|
28
|
+
return text
|
|
29
|
+
except (UnicodeError, LookupError):
|
|
30
|
+
fail()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Context:
|
|
34
|
+
"""A single budget ledger is shared by every nested parse and decoding view."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, raw, budget):
|
|
37
|
+
if (type(budget) is not dict or budget.keys() != CEILINGS.keys()
|
|
38
|
+
or any(type(v) is not int or not 0 < v <= CEILINGS[k] for k, v in budget.items())):
|
|
39
|
+
fail("NRM-PROFILE")
|
|
40
|
+
self.budget, self.raw, self.segments = budget, raw, []
|
|
41
|
+
self.usage = dict.fromkeys(budget, 0)
|
|
42
|
+
self.charge("input_bytes", len(raw))
|
|
43
|
+
self.charge("map_bytes", 2)
|
|
44
|
+
|
|
45
|
+
def charge(self, key, amount):
|
|
46
|
+
self.usage[key] += amount
|
|
47
|
+
if self.usage[key] > self.budget[key]:
|
|
48
|
+
fail("NRM-OVER-CAP")
|
|
49
|
+
|
|
50
|
+
def node(self, depth):
|
|
51
|
+
if depth > self.budget["depth"]:
|
|
52
|
+
fail("NRM-OVER-CAP")
|
|
53
|
+
self.usage["depth"] = max(self.usage["depth"], depth)
|
|
54
|
+
self.charge("nodes", 1)
|
|
55
|
+
self.charge("work", 1)
|
|
56
|
+
|
|
57
|
+
def emit(self, raw_text, locator, exact=False):
|
|
58
|
+
if not raw_text:
|
|
59
|
+
return
|
|
60
|
+
if len(locator.encode("utf-8")) > 1024:
|
|
61
|
+
fail("NRM-OVER-CAP")
|
|
62
|
+
run = 0
|
|
63
|
+
for char in raw_text:
|
|
64
|
+
run = run + 1 if unicodedata.combining(char) else 0
|
|
65
|
+
self.usage["combining_run"] = max(self.usage["combining_run"], run)
|
|
66
|
+
if run > self.budget["combining_run"]:
|
|
67
|
+
fail("NRM-OVER-CAP")
|
|
68
|
+
text = unicodedata.normalize("NFKC", raw_text)
|
|
69
|
+
text = "".join(c for c in text if unicodedata.category(c) not in {"Cf", "Cc"}
|
|
70
|
+
or c in "\n\r\t")
|
|
71
|
+
run = 0
|
|
72
|
+
for char in text:
|
|
73
|
+
run = run + 1 if unicodedata.combining(char) else 0
|
|
74
|
+
self.usage["combining_run"] = max(self.usage["combining_run"], run)
|
|
75
|
+
if run > self.budget["combining_run"]:
|
|
76
|
+
fail("NRM-OVER-CAP")
|
|
77
|
+
if not text:
|
|
78
|
+
fail("NRM-EMPTY")
|
|
79
|
+
self.charge("work", len(raw_text.encode("utf-8")) + len(text.encode("utf-8")))
|
|
80
|
+
self.charge("output_bytes", len(text.encode("utf-8")))
|
|
81
|
+
segment = dict(text=text, raw_text=raw_text, locator=locator,
|
|
82
|
+
precision="exact" if exact and text == raw_text else "container",
|
|
83
|
+
source_start=0, source_end=len(self.raw))
|
|
84
|
+
self.charge("spans", 1)
|
|
85
|
+
self.charge("map_bytes", len(canonical(segment)) + bool(self.segments))
|
|
86
|
+
self.segments.append(segment)
|
|
87
|
+
|
|
88
|
+
def parse(self, data, media, locator="root", depth=0, charset="utf-8"):
|
|
89
|
+
from formats_containers import parse_email, parse_zip
|
|
90
|
+
from formats_pdf import parse_pdf
|
|
91
|
+
from formats_structured import parse_structured
|
|
92
|
+
self.node(depth)
|
|
93
|
+
self.charge("work", len(data))
|
|
94
|
+
if not data:
|
|
95
|
+
fail("NRM-EMPTY")
|
|
96
|
+
if media not in SUPPORTED:
|
|
97
|
+
fail("NRM-UNSUPPORTED")
|
|
98
|
+
if media == "application/zip":
|
|
99
|
+
parse_zip(self, data, locator, depth)
|
|
100
|
+
elif media == "message/rfc822":
|
|
101
|
+
parse_email(self, data, locator, depth)
|
|
102
|
+
elif media == "application/pdf":
|
|
103
|
+
parse_pdf(self, data, locator, depth)
|
|
104
|
+
else:
|
|
105
|
+
if data.startswith((b"%PDF-", b"PK\x03\x04", b"PK\x05\x06", b"\x00", b"\xff\xfe", b"\xfe\xff")):
|
|
106
|
+
fail("NRM-AMBIGUOUS")
|
|
107
|
+
text = decode(data, charset)
|
|
108
|
+
self.emit(text, locator, exact=depth == 0 and media == "text/plain"
|
|
109
|
+
and data == text.encode("utf-8"))
|
|
110
|
+
parse_structured(self, text, media, locator, depth)
|