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.
Files changed (478) hide show
  1. mcp_warden_cli-2.3.0/.github/workflows/normalization.yml +43 -0
  2. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CHANGELOG.md +24 -1
  3. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/DOCUMENTATION_INDEX.md +26 -3
  4. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/PKG-INFO +23 -2
  5. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/README.md +22 -1
  6. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/RELEASING.md +27 -11
  7. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/SYSTEM_CONTEXT_DIAGRAM.md +28 -3
  8. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action/requirements.lock +3 -3
  9. mcp_warden_cli-2.3.0/components/normalizer/Dockerfile +13 -0
  10. mcp_warden_cli-2.3.0/components/normalizer/README.md +93 -0
  11. mcp_warden_cli-2.3.0/components/normalizer/THIRD_PARTY_NOTICES.md +18 -0
  12. mcp_warden_cli-2.3.0/components/normalizer/formats.py +110 -0
  13. mcp_warden_cli-2.3.0/components/normalizer/formats_containers.py +173 -0
  14. mcp_warden_cli-2.3.0/components/normalizer/formats_markdown.py +80 -0
  15. mcp_warden_cli-2.3.0/components/normalizer/formats_pdf.py +122 -0
  16. mcp_warden_cli-2.3.0/components/normalizer/formats_structured.py +192 -0
  17. mcp_warden_cli-2.3.0/components/normalizer/requirements.lock +7 -0
  18. mcp_warden_cli-2.3.0/components/normalizer/worker.py +69 -0
  19. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/AGENT_GATES.md +9 -1
  20. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/CHECKS.md +1 -0
  21. mcp_warden_cli-2.3.0/docs/CONTENT_NORMALIZATION.md +195 -0
  22. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/RESULT_INSPECTION.md +6 -0
  23. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/SPEC.md +6 -0
  24. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/WARDEN_LOCK_SCHEMA.md +4 -0
  25. mcp_warden_cli-2.3.0/docs/plans/2026-11-14-op-reference-ids.md +45 -0
  26. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/drift.ts +12 -0
  27. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/pyproject.toml +1 -1
  28. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/requirements-dev.lock +3 -3
  29. mcp_warden_cli-2.3.0/scripts/qualify_normalizer.sh +29 -0
  30. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/__init__.py +5 -3
  31. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/auth_audit.py +6 -1
  32. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/auth_refs.py +31 -3
  33. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli.py +2 -0
  34. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_guard.py +38 -1
  35. mcp_warden_cli-2.3.0/src/mcp_warden/cli_normalize.py +59 -0
  36. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/drift.py +17 -0
  37. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard.py +5 -1
  38. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_banner.py +8 -4
  39. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_loop.py +19 -0
  40. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_result.py +16 -2
  41. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/inspector.py +32 -1
  42. mcp_warden_cli-2.3.0/src/mcp_warden/normalization.py +215 -0
  43. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_guard.py +60 -0
  44. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_ingress.py +43 -0
  45. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_inspection.py +152 -0
  46. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_ipc.py +113 -0
  47. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_models.py +78 -0
  48. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_sandbox.py +226 -0
  49. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_trace.py +49 -0
  50. mcp_warden_cli-2.3.0/src/mcp_warden/normalization_validation.py +95 -0
  51. mcp_warden_cli-2.3.0/tests/fuzz/test_fuzz_normalization.py +54 -0
  52. mcp_warden_cli-2.3.0/tests/test_auth_refs_op_ids.py +99 -0
  53. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_drift.py +32 -0
  54. mcp_warden_cli-2.3.0/tests/test_normalization_contract.py +47 -0
  55. mcp_warden_cli-2.3.0/tests/test_normalization_coordinator.py +125 -0
  56. mcp_warden_cli-2.3.0/tests/test_normalization_e2e.py +125 -0
  57. mcp_warden_cli-2.3.0/tests/test_normalization_integration.py +232 -0
  58. mcp_warden_cli-2.3.0/tests/test_normalization_sandbox.py +212 -0
  59. mcp_warden_cli-2.3.0/tests/test_normalizer_formats.py +403 -0
  60. mcp_warden_cli-2.3.0/vectors/cases/drift-digest-mismatch-unexplained.json +119 -0
  61. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/manifest.json +6 -1
  62. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/tools/generate.py +1 -0
  63. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  64. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  65. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  66. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  67. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/action-test.yml +0 -0
  68. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/deps-locked.yml +0 -0
  69. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/docs.yml +0 -0
  70. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/examples.yml +0 -0
  71. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/integrity-gate.yml +0 -0
  72. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/release.yml +0 -0
  73. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.github/workflows/sigstore-fixture.yml +0 -0
  74. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.gitignore +0 -0
  75. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.gitleaks.toml +0 -0
  76. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/.pre-commit-hooks.yaml +0 -0
  77. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CODEOWNERS +0 -0
  78. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CODE_OF_CONDUCT.md +0 -0
  79. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/CONTRIBUTING.md +0 -0
  80. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/LICENSE +0 -0
  81. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/Makefile +0 -0
  82. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/SECURITY.md +0 -0
  83. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action/build-requirements.lock +0 -0
  84. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/action.yml +0 -0
  85. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/AGENT_TRUST_KERNEL.md +0 -0
  86. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/ARTIFACT_TRUST.md +0 -0
  87. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/COMMUNITY_CORPUS.md +0 -0
  88. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/CONTENT_ENVELOPE.md +0 -0
  89. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/DECISION_RECEIPTS.md +0 -0
  90. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/DOCTOR.md +0 -0
  91. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/GUARD_PROXY.md +0 -0
  92. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/GUARD_PROXY_V3.md +0 -0
  93. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/PIN_CHECK_DEMO.md +0 -0
  94. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/POLICY_ENFORCEMENT.md +0 -0
  95. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/POLICY_MODEL.md +0 -0
  96. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/SIGNING.md +0 -0
  97. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/THREAT_MODEL.md +0 -0
  98. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/THREAT_MODEL_V2.md +0 -0
  99. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/WARDEN_LOCK_EXAMPLE.md +0 -0
  100. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/archive/2026-10-02-runtime-cli-examples.md +0 -0
  101. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/archive/2026-10-04-readme-community-consensus.md +0 -0
  102. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-18-agent-trust-kernel-design.md +0 -0
  103. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-18-content-envelope-design.md +0 -0
  104. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-decision-receipts-design.md +0 -0
  105. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-decision-receipts-implementation.md +0 -0
  106. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-07-19-pdp-pep-design.md +0 -0
  107. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-02-pypi-automation-repair.md +0 -0
  108. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-02-tool-integrity-upgrade.md +0 -0
  109. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-03-checkpoint-artifact-trust.md +0 -0
  110. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-04-dse717-council-fixes.md +0 -0
  111. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs/plans/2026-10-04-dse717-reconciliation.md +0 -0
  112. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/artifact-trust.md +0 -0
  113. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/checklist.md +0 -0
  114. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/comparison.md +0 -0
  115. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/decision-receipts.md +0 -0
  116. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/index.md +0 -0
  117. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/lock-format.md +0 -0
  118. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/pin-in-ci.md +0 -0
  119. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/quickstart.md +0 -0
  120. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/rug-pull.md +0 -0
  121. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/docs-site/tool-poisoning.md +0 -0
  122. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/README.md +0 -0
  123. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/README.md +0 -0
  124. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/evidence-fail.json +0 -0
  125. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/evidence-pass.json +0 -0
  126. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/gate-policy.json +0 -0
  127. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/agent-gates/mcp-config-audit-demo.json +0 -0
  128. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/matrix-multiple-servers.yml +0 -0
  129. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/pin-on-merge-check-on-pr.yml +0 -0
  130. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/private-repo-no-sarif.yml +0 -0
  131. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/github-actions/sarif-upload.yml +0 -0
  132. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/gitlab-ci/.gitlab-ci.yml +0 -0
  133. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-everything/README.md +0 -0
  134. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-everything/warden.lock +0 -0
  135. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-memory/README.md +0 -0
  136. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-memory/warden.lock +0 -0
  137. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-sequential-thinking/README.md +0 -0
  138. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pinned-servers/server-sequential-thinking/warden.lock +0 -0
  139. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/examples/pre-commit/.pre-commit-config.yaml +0 -0
  140. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/mkdocs.yml +0 -0
  141. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/.gitignore +0 -0
  142. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/LICENSE +0 -0
  143. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/README.md +0 -0
  144. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/package-lock.json +0 -0
  145. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/package.json +0 -0
  146. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/capabilities.ts +0 -0
  147. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/digest.ts +0 -0
  148. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/index.ts +0 -0
  149. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/jcs.ts +0 -0
  150. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/lock.ts +0 -0
  151. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/py.ts +0 -0
  152. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/src/skeleton.ts +0 -0
  153. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/test/vectors.test.ts +0 -0
  154. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/packages/lock-ts/tsconfig.json +0 -0
  155. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/scripts/verify_pypi_oidc.py +0 -0
  156. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/adapter_conformance.py +0 -0
  157. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/artifact_payload.py +0 -0
  158. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/artifact_trust.py +0 -0
  159. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/capture.py +0 -0
  160. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/check_core.py +0 -0
  161. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks.py +0 -0
  162. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks_secret.py +0 -0
  163. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/checks_supply.py +0 -0
  164. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_auth.py +0 -0
  165. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_corpus.py +0 -0
  166. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_deploy_gate.py +0 -0
  167. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_diff.py +0 -0
  168. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_doctor.py +0 -0
  169. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_lock.py +0 -0
  170. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_sign.py +0 -0
  171. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/cli_trust.py +0 -0
  172. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/content_envelope.py +0 -0
  173. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/content_models.py +0 -0
  174. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus.py +0 -0
  175. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_coordinate.py +0 -0
  176. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_trust.py +0 -0
  177. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/corpus_verify.py +0 -0
  178. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_governor.py +0 -0
  179. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_models.py +0 -0
  180. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/decision_receipts.py +0 -0
  181. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/deploy_gate.py +0 -0
  182. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor.py +0 -0
  183. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_discovery.py +0 -0
  184. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_funnel.py +0 -0
  185. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_jsonc.py +0 -0
  186. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/doctor_paths.py +0 -0
  187. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/drift_tool_metadata.py +0 -0
  188. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/emit_res.py +0 -0
  189. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/emitters.py +0 -0
  190. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/enforcement_result_v2.py +0 -0
  191. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_coordinator.py +0 -0
  192. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_floor.py +0 -0
  193. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_helpers.py +0 -0
  194. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_latch.py +0 -0
  195. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_models.py +0 -0
  196. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_recovery.py +0 -0
  197. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_reference.py +0 -0
  198. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/evidence_state.py +0 -0
  199. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/executable_bundle.py +0 -0
  200. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/framing.py +0 -0
  201. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/governance_integrity.py +0 -0
  202. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/governed_decision.py +0 -0
  203. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_io.py +0 -0
  204. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_lifecycle.py +0 -0
  205. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_list_gate.py +0 -0
  206. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/guard_strict.py +0 -0
  207. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/handler_identity.py +0 -0
  208. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/hashing.py +0 -0
  209. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/lockfile.py +0 -0
  210. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/models.py +0 -0
  211. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/net_rules.py +0 -0
  212. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_decision.py +0 -0
  213. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement.py +0 -0
  214. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement_v2.py +0 -0
  215. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_enforcement_v2_helpers.py +0 -0
  216. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_eval.py +0 -0
  217. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/policy_model.py +0 -0
  218. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/precommit.py +0 -0
  219. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/provenance.py +0 -0
  220. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_conformance.py +0 -0
  221. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_conformance_models.py +0 -0
  222. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_kernel.py +0 -0
  223. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_log.py +0 -0
  224. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_models.py +0 -0
  225. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_projection.py +0 -0
  226. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_replay.py +0 -0
  227. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/receipt_verification.py +0 -0
  228. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/redact.py +0 -0
  229. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_catalog.py +0 -0
  230. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_dns.py +0 -0
  231. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_net.py +0 -0
  232. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/res_rules.py +0 -0
  233. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/result_inspection.py +0 -0
  234. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/rule_engine.py +0 -0
  235. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/rule_models.py +0 -0
  236. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/schema_diff.py +0 -0
  237. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/signer_authorization.py +0 -0
  238. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/signing.py +0 -0
  239. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/tokenizer.py +0 -0
  240. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/src/mcp_warden/wire_block.py +0 -0
  241. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/__init__.py +0 -0
  242. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/dse717_council_fixtures.py +0 -0
  243. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/_sdk_compat.py +0 -0
  244. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/capability_server.py +0 -0
  245. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean.warden.lock +0 -0
  246. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean_listchange.warden.lock +0 -0
  247. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/clean_server.py +0 -0
  248. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/README.md +0 -0
  249. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/corpus/attesters.json +0 -0
  250. {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
  251. {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
  252. {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
  253. {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
  254. {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
  255. {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
  256. {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
  257. {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
  258. {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
  259. {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
  260. {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
  261. {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
  262. {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
  263. {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
  264. {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
  265. {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
  266. {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
  267. {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
  268. {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
  269. {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
  270. {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
  271. {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
  272. {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
  273. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/crash_server.py +0 -0
  274. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/fault_guard_launcher.py +0 -0
  275. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/gen_corpus.py +0 -0
  276. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/legacy-v3.warden.lock +0 -0
  277. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/listchange_server.py +0 -0
  278. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/mutated_server.py +0 -0
  279. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/overcap_server.py +0 -0
  280. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/poison_server.py +0 -0
  281. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/tool_integrity_server.py +0 -0
  282. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fixtures/tool_metadata_listchange_server.py +0 -0
  283. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/__init__.py +0 -0
  284. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/conftest.py +0 -0
  285. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_ansi.py +0 -0
  286. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_content_envelope.py +0 -0
  287. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_domain.py +0 -0
  288. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_framing.py +0 -0
  289. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_policy_decision.py +0 -0
  290. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_receipts.py +0 -0
  291. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/fuzz/test_fuzz_redact.py +0 -0
  292. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/receipt_fixtures.py +0 -0
  293. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_action_yml.py +0 -0
  294. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_adapter_conformance.py +0 -0
  295. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_agent_gates_examples.py +0 -0
  296. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_artifact_trust.py +0 -0
  297. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_artifact_trust_integration.py +0 -0
  298. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_auth_audit.py +0 -0
  299. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_capabilities.py +0 -0
  300. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_http.py +0 -0
  301. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_model_dump.py +0 -0
  302. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_page_cap.py +0 -0
  303. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_capture_pagination.py +0 -0
  304. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_checks.py +0 -0
  305. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_cli_trust.py +0 -0
  306. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_cli_version.py +0 -0
  307. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_content_envelope.py +0 -0
  308. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_corpus.py +0 -0
  309. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_corpus_cli.py +0 -0
  310. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_decision_receipts.py +0 -0
  311. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_deploy_gate.py +0 -0
  312. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_diff.py +0 -0
  313. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor.py +0 -0
  314. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor_cli.py +0 -0
  315. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_doctor_security.py +0 -0
  316. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_fixes.py +0 -0
  317. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_floors.py +0 -0
  318. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_council_rotation.py +0 -0
  319. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_dse717_review_regressions.py +0 -0
  320. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_e2e_pin_check.py +0 -0
  321. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_emitters.py +0 -0
  322. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_coordinator.py +0 -0
  323. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_recovery.py +0 -0
  324. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_state.py +0 -0
  325. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_evidence_state_v2_contract.py +0 -0
  326. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_framing.py +0 -0
  327. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_banner.py +0 -0
  328. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_platform.py +0 -0
  329. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_posture.py +0 -0
  330. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_proxy.py +0 -0
  331. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_strict.py +0 -0
  332. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_v3.py +0 -0
  333. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_guard_windows.py +0 -0
  334. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_handler_boundary.py +0 -0
  335. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_hashing.py +0 -0
  336. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_inspect_parity.py +0 -0
  337. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_inspection_policy.py +0 -0
  338. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_lock_sign.py +0 -0
  339. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_lockfile.py +0 -0
  340. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy.py +0 -0
  341. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_decision.py +0 -0
  342. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_enforcement.py +0 -0
  343. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_policy_enforcement_v2.py +0 -0
  344. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_precommit.py +0 -0
  345. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_provenance.py +0 -0
  346. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_conformance.py +0 -0
  347. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_hardening.py +0 -0
  348. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_log.py +0 -0
  349. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_projection.py +0 -0
  350. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_replay.py +0 -0
  351. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_receipt_verification.py +0 -0
  352. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_release_oidc.py +0 -0
  353. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_res_dns.py +0 -0
  354. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_result_inspection.py +0 -0
  355. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_rule_engine.py +0 -0
  356. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_schema_diff.py +0 -0
  357. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_schema_diff_refs.py +0 -0
  358. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_signing.py +0 -0
  359. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_signing_unit.py +0 -0
  360. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_spec_consistency.py +0 -0
  361. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_spec_vectors.py +0 -0
  362. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tokenizer.py +0 -0
  363. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tool_integrity.py +0 -0
  364. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_tool_integrity_guard.py +0 -0
  365. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_wire_block.py +0 -0
  366. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/tests/test_workflow_pins.py +0 -0
  367. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/README.md +0 -0
  368. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-control-escapes.json +0 -0
  369. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-deep-nesting.json +0 -0
  370. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-depth-512-accepted.json +0 -0
  371. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-array.json +0 -0
  372. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-object.json +0 -0
  373. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-empty-string.json +0 -0
  374. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-key-escapes.json +0 -0
  375. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-nested-arrays.json +0 -0
  376. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-numbers-boundaries.json +0 -0
  377. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-numbers-es6.json +0 -0
  378. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-scalars.json +0 -0
  379. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-sorted-keys-utf16.json +0 -0
  380. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-surrogate-key-order.json +0 -0
  381. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/canonical-unicode-literal.json +0 -0
  382. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-absence-rules.json +0 -0
  383. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-capabilities-and-refs.json +0 -0
  384. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-clean-fixture.json +0 -0
  385. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-entry-sorting-astral.json +0 -0
  386. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-entry-sorting.json +0 -0
  387. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-enum-constraints-skeleton.json +0 -0
  388. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-http-url-server.json +0 -0
  389. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-malformed-input-schema.json +0 -0
  390. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-minimal-single-tool.json +0 -0
  391. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-empty.json +0 -0
  392. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-full.json +0 -0
  393. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/digest-tool-metadata-null.json +0 -0
  394. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-capability-added.json +0 -0
  395. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-capability-removed.json +0 -0
  396. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-description-and-schema.json +0 -0
  397. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-description-modified.json +0 -0
  398. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-inspection-policy-modified.json +0 -0
  399. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-mixed-multi-entry.json +0 -0
  400. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-no-drift.json +0 -0
  401. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-added.json +0 -0
  402. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-modified.json +0 -0
  403. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-prompt-removed.json +0 -0
  404. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-added.json +0 -0
  405. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-modified.json +0 -0
  406. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-resource-removed.json +0 -0
  407. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-additional-props-opened-to-object.json +0 -0
  408. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-additional-props-opened.json +0 -0
  409. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-array-items-recursed.json +0 -0
  410. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-bound-removed.json +0 -0
  411. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-maxlength-up.json +0 -0
  412. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-minimum-lowered.json +0 -0
  413. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-pattern-removed.json +0 -0
  414. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-relaxed-required-to-optional.json +0 -0
  415. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-constraint-tightened.json +0 -0
  416. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-cosmetic-modified.json +0 -0
  417. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-added.json +0 -0
  418. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-disjoint-is-widened.json +0 -0
  419. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-narrowed.json +0 -0
  420. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-removed.json +0 -0
  421. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-enum-widened.json +0 -0
  422. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-opaque-ref.json +0 -0
  423. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-ref-redacted.json +0 -0
  424. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-modified-v1-fallback.json +0 -0
  425. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-added.json +0 -0
  426. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-constraint-relaxed.json +0 -0
  427. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-cosmetic-modified.json +0 -0
  428. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-extension-null.json +0 -0
  429. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-local-ref.json +0 -0
  430. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-ref-redacted.json +0 -0
  431. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-removed.json +0 -0
  432. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-out-type-broadened.json +0 -0
  433. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-pattern-changed-tightened.json +0 -0
  434. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-per-fact-emission.json +0 -0
  435. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-property-added.json +0 -0
  436. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-property-removed.json +0 -0
  437. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-ref-resolved-granular.json +0 -0
  438. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-added.json +0 -0
  439. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-removed.json +0 -0
  440. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-required-unconstrained-added.json +0 -0
  441. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-any-to-typed.json +0 -0
  442. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-broadened.json +0 -0
  443. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-changed.json +0 -0
  444. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-type-narrowed.json +0 -0
  445. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-unconstrained-added.json +0 -0
  446. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-schema-version-migrated.json +0 -0
  447. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-server-identity-url.json +0 -0
  448. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-server-identity.json +0 -0
  449. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-added.json +0 -0
  450. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-destructiveHint.json +0 -0
  451. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-explicit-null.json +0 -0
  452. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-extension.json +0 -0
  453. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-idempotentHint.json +0 -0
  454. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-nested-null.json +0 -0
  455. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-openWorldHint.json +0 -0
  456. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-readOnlyHint.json +0 -0
  457. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-annotations-removed.json +0 -0
  458. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-tool-removed.json +0 -0
  459. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-unapproved-change.json +0 -0
  460. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-v3-to-v4-migration.json +0 -0
  461. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/drift-v3-unapproved-migration.json +0 -0
  462. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-deep-nesting-2000.json +0 -0
  463. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-depth-513-rejected.json +0 -0
  464. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-invalid-json.json +0 -0
  465. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-lock-depth-1200-rejected.json +0 -0
  466. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-missing-overall-digest.json +0 -0
  467. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-missing-pin.json +0 -0
  468. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-schema-version-above-implemented.json +0 -0
  469. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-schema-version-not-integer.json +0 -0
  470. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-server-missing-command-digest.json +0 -0
  471. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-tool-missing-entry-digest.json +0 -0
  472. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-tools-not-array.json +0 -0
  473. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-high.json +0 -0
  474. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-key.json +0 -0
  475. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-unpaired-surrogate-low.json +0 -0
  476. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-v4-missing-annotations_hash.json +0 -0
  477. {mcp_warden_cli-2.2.0 → mcp_warden_cli-2.3.0}/vectors/cases/malformed-v4-missing-output_schema_hash.json +0 -0
  478. {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.2.0...HEAD
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-10-22
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 archived to [`docs/PIN_CHECK_DEMO.md`](docs/PIN_CHECK_DEMO.md) to hold the 500-line core-doc limit), 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)** |
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.2.0
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-10-22
37
+ Last Updated: 2026-11-14
38
38
 
39
39
  [![CI](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml/badge.svg)](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml)
40
40
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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-10-22
3
+ Last Updated: 2026-11-14
4
4
 
5
5
  [![CI](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml/badge.svg)](https://github.com/DataScience-EngineeringExperts/mcp-warden/actions/workflows/integrity-gate.yml)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- After the publisher is aligned and authentication succeeds, rerun only the failed
164
- job from the original release run, using its retained build artifacts:
165
-
166
- ```bash
167
- gh run rerun 36960647544 --failed
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-10-22
3
+ Last Updated: 2026-11-14
4
4
 
5
- **CLI 2.0.0 / schema level 4** extends capture/lock/check to complete tool annotations and output
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
- > publisher alignment must be verified independently. See [`RELEASING.md`](RELEASING.md).
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.1 \
235
- --hash=sha256:aa38ed19bcc084ba42782a73255b3582283eced7ad6dddbd6695189e69adfb75 \
236
- --hash=sha256:b31553efa588ae44bc306f863c785c5333a9ecc091248c6ee68b4b6c87fdedfb
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)