messagefoundry 0.2.0__tar.gz → 0.2.1__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.
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/release-sync-check.yml +6 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/security.yml +9 -2
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/CHANGELOG.md +18 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/PKG-INFO +1 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/__init__.py +1 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/__main__.py +18 -3
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/app.py +57 -3
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/models.py +21 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/__init__.py +16 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/client.py +19 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/connections.py +39 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/engine.py +88 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/checks.py +7 -1
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_anon_core.py +13 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_anon_parity.py +5 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cli.py +18 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_widgets.py +75 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_config.py +7 -0
- messagefoundry-0.2.1/tests/test_stats_reset.py +238 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_verify.py +39 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.claude/settings.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.dockerignore +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.gitattributes +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/CODEOWNERS +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/SECURITY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/dependabot.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/benchmark.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/ci.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/cla.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/dependabot-auto-merge.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/dependabot-lock-resync.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/release.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.github/workflows/vuln-metrics.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.gitignore +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.gitleaks.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.pre-commit-config.yaml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/.semgrep/messagefoundry.yml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/CLA.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/CLAUDE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/CODE_OF_CONDUCT.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/COMMERCIAL-LICENSE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/CONTRIBUTING.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/GOVERNANCE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/LICENSE +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/MAINTAINERS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/NOTICE +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/Dockerfile +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/compose.yaml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/k8s/secret.example.yaml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/k8s/statefulset.yaml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/locks/requirements-core.lock +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/locks/requirements-sqlserver.lock +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/secrets.env.example +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/smoke/Dockerfile +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/smoke/config/IB_Test_ADT.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docker/smoke/send_adt.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/ADOPTER-CI.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/AI.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/ARCHITECTURE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/BACKLOG.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CI-QUALITY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CLUSTERING.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CONFIGURATION.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CONNECTIONS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CONTAINER-EXPOSURE-EVALUATION.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CONTRIBUTOR-FIRST-ISSUES.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/CONTRIBUTOR-PROGRAM-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/COUNSEL-ENGAGEMENT-BRIEF.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/DEPLOY-SERVER-DB.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/DEPLOYMENT.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/DICOM.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/DUAL_LICENSING_PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/EARLY-ADOPTER-GUIDE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/FEATURE-MAP.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/HL7-VALIDATION.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/INSTALL-GUIDE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/LOAD-TESTING.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/MENTAL-MODEL.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/MessageFoundry-Mental-Model.docx +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/PHI.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/REMOTE-CONSOLE-CUSTOMER-GUIDE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/REMOTE-CONSOLE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/SECURITY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/SERVICE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/SUPPORT-POLICY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/SYSTEM-REQUIREMENTS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/Secure_AI_Development_Standards.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/Secure_Development_Standards.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/TEE-RELAY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/THROUGHPUT-IMPROVEMENTS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/USER-GUIDE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/WORKTREES.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0001-staged-pipeline-architecture.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0002-phase2-transport-security-and-strong-auth.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0003-non-hl7-transports-database-rest-soap.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0004-payload-agnostic-ingress.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0005-transform-accessible-state.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0006-external-data-lookups.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0007-gui-manageable-connections-toml.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0008-cluster-observability-api.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0009-run-scoped-context-providers.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0010-handler-callable-db-lookup.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0011-timer-scheduled-source.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0012-x12-edi-codec.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0013-increment-2-reingress-design.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0013-query-response-orchestration.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0014-alerting-rules-engine.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0015-ws-soap-outbound-mtls-wssecurity.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0016-synchronous-x12-request-response.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0017-consumer-deployment-model.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0018-per-message-signatures-accepted-risk.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0019-pluggable-keyprovider-hsm-kms-vault.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0020-protocol-diagnostic-capture.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0021-inbound-ack-nak-capture-response-sent.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0022-fhir-resource-codec-rest-client.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0024-smart-backend-services-token-provider.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0025-dicom-codec-store-connectors.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0026-off-box-egress-update-check.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0028-base64-binary-carriage-codec.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0030-anonymization-test-harness-tee.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0031-startup-connection-fault-isolation.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/0032-console-desktop-launch.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/adr/TEMPLATE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-components.png +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-components.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-config-graph.png +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-config-graph.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-diagram.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-message-flow.png +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-message-flow.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-topology.png +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/architecture-topology.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/TUNING-BASELINE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/environment.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/failover-postgres.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/failover-sqlserver.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/reference-postgres.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/reference-sqlite.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/results/2026-06-16-ci-linux/reference-sqlserver.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/benchmarks/step-b-write-amplification.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/hl7-message-ordering-reference.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/message-ordering-design.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/ASVS-OPTION-A-MULTISESSION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/ASVS-PARTIALS-SWEEP-MULTISESSION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/DOGFOOD-BACKLOG-MULTISESSION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/MULTISESSION-PLAN-3.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/MULTISESSION-PLAN-v0.2.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/MULTISESSION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/PLAN-3-LANE-HANDOFFS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/V0.2-LANE-HANDOFFS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/v0.1-EXECUTION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/v0.1-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/releases/v0.1.0-PRETAG-CHECKLIST.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/research/cloud-deployment-research-2026-06.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/research/config-ux-review.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/research/non-hl7-transform-components.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/reviews/DEPENDENCY-INFOSEC-POSTURE-2026-06-23.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/reviews/FULL-REVIEW-2026-06-10.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ADVISORY-PROCESS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-FAILS-REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-L2-PHASE0-CHANGES.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-L2-REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-L3-ASSESSMENT.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-L3-REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/ASVS-L3-STATUS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/BEYOND-ASVS-L3-ONEPAGE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/BEYOND-ASVS-L3-REMEDIATION-PLAN-ONEPAGE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/BEYOND-ASVS-L3-REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/BEYOND-ASVS-L3.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/DEP-CVE-RUNBOOK.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/DEPENDENCY-METRICS.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/MEFOR-Code-Review-Checklist.xlsx +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/PHASE-8C-RBAC.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/PUBLISHING.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/RCA-TEMPLATE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/RELEASE-GATE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/REVIEW-2026-06-07.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SDS-CONFORMANCE-REVIEW-2026-06-12.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SDS-REMEDIATION-PLAN.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SECURITY-POSTURE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SOUP-DEPENDENCY-HANDLING.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SOUP-REVIEW-2026-06-18.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/SOUP-REVIEW-PROCEDURE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/security/THREAT-MODEL.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/testing/VERIFY.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/testing/WIN2025-ACCEPTANCE.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/docs/testing/WIN2025-TEST-MATRIX.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/environments/dev.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/environments/prod.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/__main__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/__main__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/matrix.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/probes.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/acceptance/runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/compose.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/config/coverage.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/config/load/_shape.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/config/load/graph.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/file_panel.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/file_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/corpus.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/correlator.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/enginepoll.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/failover.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/failover_track.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/governor.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/ids.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/metrics.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profile.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/closed-loop.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/failover.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/fanout-baseline.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/reference.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/smoke-sqlserver.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/smoke.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/profiles/soak.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/sender.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/load/sink.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/mllp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/monitor.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/receive.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/__main__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/capture.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/compare.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/normalize.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/reconcile/report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/scenarios.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/send.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/harness/window.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/.gitignore +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/.vscodeignore +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/esbuild.js +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/media/hl7schema.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/media/icon.png +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/media/icon.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/package-lock.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/package.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/snippets/messagefoundry.code-snippets +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/aiPolicy.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/alertEditor.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/auth.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/chat.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/cli.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/completion.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/connectionEditor.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/engineClient.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/extension.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/generate.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/git.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/graphTree.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/home.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/newRoute.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/promote.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/sourceControl.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/test/runTest.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/test/suite/chat.test.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/test/suite/extension.test.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/test/suite/index.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/testBench.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/src/validate.ts +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/tsconfig.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/ide/tsconfig.test.json +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/mefor.code-workspace +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/adr_analyze.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/_pools.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/hl7.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/keying.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/leak.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/rules.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/anon/surrogates.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/approvals.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/auth_models.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/auth_routes.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/field_authz.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/metrics.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/security.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/api/tls.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/data/common_passwords.NOTICE +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/data/common_passwords.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/identity.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/ldap.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/notifications.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/passwords.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/permissions.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/policy.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/ratelimit.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/service.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/tokens.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/auth/totp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/checks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/active_environment.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/ai_policy.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/alerts_edit.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/code_sets.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/connections_edit.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/connections_file.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/db_lookup.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/environments.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/ingest_time.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/models.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/reference.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/response.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/run_context.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/settings.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/state.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/tls_policy.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/config/wiring.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/__main__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/_async.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/alerts_page.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/change_password.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/dead_letters_page.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/delegates.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/alerts.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/connections.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/dead-letters.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/engine-status.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/log-search.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/logo-lockup.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/icons/users.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/login.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/mfa.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/reauth.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/resources/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/resources/app.ico +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/resources/app.svg +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/search.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/service_control.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/sessions.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/shell.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/status.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/theme.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/users_page.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/console/widgets.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/_core.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/_hl7data.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/adt.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/all_types.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/bar.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/dft.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/documents.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/mdm.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/mfn.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/oml.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/orl.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/orm.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/oru.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/ras.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/rde.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/siu.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/generators/vxu.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/hl7schema.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/last_resort.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/logging_setup.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/binary.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/consistency.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/_deps.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/_util.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/dataset.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/errors.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/hl7_map.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/dicom/peek.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/fhir/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/fhir/_deps.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/fhir/errors.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/fhir/peek.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/fhir/resource.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/groups.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/message.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/peek.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/split.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/summary.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/tree.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/validate.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/delimiters.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/errors.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/interchange.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/message.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/parsing/x12/peek.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/alert_sinks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/alerts.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/cert_expiry.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/cluster.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/cluster_sqlserver.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/config_convergence.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/dryrun.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/leader_tasks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/reference_sync.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/retention.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/security_notify.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/state_convergence.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/pipeline/wiring_runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/py.typed +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/redaction.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/scaffold.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/secrets_dpapi.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/audit_tee.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/base.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/crypto.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/keyprovider.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/postgres.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/sqlserver.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/store/store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/timezone.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/base.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/database.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/dicom.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/dicomweb.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/fhir.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/file.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/framing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/loopback.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/mllp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/remotefile.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/rest.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/signing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/smart.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/soap.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/tcp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/timer.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/transports/x12.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/model.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/messagefoundry/verify/smoke.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/pyproject.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/requirements.lock +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_ACME_ADT.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_FHIR_INTAKE.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_IMMUNIZATION_VXU.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_PARTNER_X12.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_RADIOLOGY_SR.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/IB_RTE_ELIGIBILITY.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/adt.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/codesets/event_labels.csv +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/codesets/facility_mnemonics.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/config/connections.toml +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/consistency/validated_adt.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/dicom/generate_sr_sample.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/adt_a01.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/adt_batch.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/.gitattributes +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/adt_a01.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/adt_a03.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/batch_18_messages.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/erp_z99_v231.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/omd_o03.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/omd_o03_rep.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/hapi-hl7v2/oml_o21.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/messages/x12_270_eligibility.edi +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/results_relay/README.md +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/results_relay/codesets/test_codes.csv +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/results_relay/messages/oru_all_cancelled.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/results_relay/messages/oru_results.hl7 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/results_relay/results_relay.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/samples/send_mllp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/console/install-console-shortcut.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/console/pack_ico.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/console/uninstall-console-shortcut.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/dev/postgres.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/dev/sqlserver-docker.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/dev/sqlserver.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/hooks/block-blanket-git-stage.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/publish/check_release_sync.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/publish/publish-denylist.txt +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/publish/publish.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/publish/scan_forbidden.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/security/crypto_inventory_check.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/security/vuln_metrics.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/service/install-service.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/service/uninstall-service.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/soak/store_soak.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/trace_icon.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/worktree/new.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/worktree/remove.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/worktree/session-context.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/scripts/worktree/spawn.ps1 +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/__main__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/__init__.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/_hl7data.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/_pools.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/hl7.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/keying.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/leak.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/rules.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/anon/surrogates.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/compare.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/correlate.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/hl7_fields.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/mefor_api.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/mllp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/relay.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tee/store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/_dicom_sample.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/_failover_load_support.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/_fhir_fixtures.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/conftest.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_acceptance_framework.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_active_environment.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_ad_group_scope.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_admin_new_ip.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_adr_analyze.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_ai_policy.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_alert_rules.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_alert_sinks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_alerts_edit.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_alerts_rules_api.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_anon_integration.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_api.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_api_auth.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_api_reload.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_api_tls.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_approvals.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_asvs_phase0.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_audit_integrity.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_audit_offbox_tee.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_core.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_entry_hardening.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_hardening.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_service.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_session_lifecycle.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_auth_store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_binary_carriage.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cert_expiry.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_channel_rbac.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_checks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cluster.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cluster_failover_postgres.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cluster_failover_sqlserver.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cluster_graph_gating.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_cluster_lease.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_code_sets.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_connection_api.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_connection_resilience.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_connections_cli.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_connections_file.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_consistency.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_alerts.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_auth.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_client.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_dead_letters.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_hardening.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_icon.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_password.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_sessions.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_status.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_step_up.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_theme.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_console_users.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_database_connector_integration.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_database_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_db_lookup.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_db_lookup_live_runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_delivery_settings.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dependency_boundaries.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dicom_codec.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dicom_scp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dicom_scu.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dicom_wiring.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dicomweb.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_dryrun.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_ed_documents.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_ed_documents_e2e.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_egress_allowlist.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_environments.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_fhir_parsing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_fhir_resource.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_fhir_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_field_authz.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_fifo_ordering.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_generate_cli.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_generated_adt.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_generators_core.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_generators_types.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_groups.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_compose.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_config.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_faults.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_file.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_monitor.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_harness_scenarios.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_hl7_core_features.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_hl7schema.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_inbound_bind.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_ingest_time.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_keyprovider.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_last_resort.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_leader_tasks.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_corpus.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_failover_postgres.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_failover_sqlserver.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_failover_unit.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_metrics.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_profile.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_runner.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_sender.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_load_sink.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_logging.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_message.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_message_split.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_metrics_exporter.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_mfa.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_mllp_encoding_override.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_mllp_tls.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_operability_config.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_outbound_signing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_outbound_simulate.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_packaging.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_parse_tree.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_parsing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_payload_agnostic_ingress.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_postgres_store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_reconcile_capture.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_reconcile_compare.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_reconcile_harness.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_redaction.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_reference_sets.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_reingress.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_remotefile_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_response_capture.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_rest_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_retention.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_run_context.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_scaffold.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_scan_forbidden.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_secrets_dpapi.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_security_notify.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_security_static.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_service_control.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_settings.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_smart_backend.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_soap_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_soap_wssecurity.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_sqlserver_coordinator.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_sqlserver_store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_staged_pipeline.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_startup_fault_isolation.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_step_up.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_store_backend.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_store_encryption.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_store_file_hardening.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_store_read_pool.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_summary.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_task_resilience.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tcp_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_cli.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_compare.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_correlate.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_hl7_fields.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_mefor_api.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_mllp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_relay.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_report.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tee_store.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_timer_source.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_timezone.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_tls_policy.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_totp.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_transform_state.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_transports.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_version.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_win2025_acceptance.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_wiring.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_wiring_engine.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_wiring_reload.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_wiring_serve.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_x12_parsing.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_x12_rte.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/tests/test_x12_transport.py +0 -0
- {messagefoundry-0.2.0 → messagefoundry-0.2.1}/uv.lock +0 -0
|
@@ -32,6 +32,12 @@ jobs:
|
|
|
32
32
|
python-version: "3.13"
|
|
33
33
|
- name: Check tag / PyPI / mirror are in sync
|
|
34
34
|
run: |
|
|
35
|
+
# The script lives under the deny-listed scripts/publish/, so it is ABSENT on the OSS mirror;
|
|
36
|
+
# the sync check only runs on the private repo (the publish source). Skip where it's absent.
|
|
37
|
+
if [ ! -f scripts/publish/check_release_sync.py ]; then
|
|
38
|
+
echo "scripts/publish/check_release_sync.py absent (OSS mirror) — skipping the release-sync check."
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
35
41
|
# `packaging` gives canonical version normalization (so a "0.1.0-rc1" tag and PyPI's
|
|
36
42
|
# "0.1.0rc1" compare equal); the script falls back to a naive form if it's absent.
|
|
37
43
|
python -m pip install --upgrade pip packaging
|
|
@@ -202,5 +202,12 @@ jobs:
|
|
|
202
202
|
with:
|
|
203
203
|
python-version: "3.13"
|
|
204
204
|
- name: Scan the publishable subset for forbidden content
|
|
205
|
-
# Stdlib-only scanner (no install). Exits non-zero — failing the build — on any hit.
|
|
206
|
-
|
|
205
|
+
# Stdlib-only scanner (no install). Exits non-zero — failing the build — on any hit. The scanner
|
|
206
|
+
# lives under the deny-listed scripts/publish/, so it is ABSENT on the OSS mirror — there's
|
|
207
|
+
# nothing to gate there (everything is already the published subset); skip rather than error.
|
|
208
|
+
run: |
|
|
209
|
+
if [ -f scripts/publish/scan_forbidden.py ]; then
|
|
210
|
+
python scripts/publish/scan_forbidden.py --published
|
|
211
|
+
else
|
|
212
|
+
echo "scripts/publish/scan_forbidden.py absent (OSS mirror) — skipping the publish leak-gate."
|
|
213
|
+
fi
|
|
@@ -6,6 +6,21 @@ All notable changes to MessageFoundry are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.1] — 2026-06-23 — Early Access
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **Windows: `messagefoundry --help` crashed on a legacy codepage** — the top-level help rendered a
|
|
13
|
+
non-cp1252 character (a `->` arrow in the `adr-analyze` subcommand help, new in 0.2.0), so `--help`
|
|
14
|
+
aborted with `UnicodeEncodeError` on a cp1252/charmap console (cmd, PowerShell, or any redirected
|
|
15
|
+
stdout). `main()` now reconfigures stdout/stderr with `errors="replace"` and the help text is ASCII;
|
|
16
|
+
the machine-read JSON introspection subcommands are unaffected (`json.dumps(ensure_ascii=True)`).
|
|
17
|
+
- **`verify --section host` crashed without the `[console]` extra** — `check_console_no_window()`
|
|
18
|
+
resolved a console submodule via `find_spec`, which imported the console package and its eager `httpx`
|
|
19
|
+
dependency, so a `[sqlserver]`-only install aborted with `ModuleNotFoundError: No module named 'httpx'`
|
|
20
|
+
instead of skipping the console check. The console package now imports its API client lazily (PEP 562
|
|
21
|
+
`__getattr__`), so resolving a submodule no longer requires `httpx`, and the check degrades to SKIP if a
|
|
22
|
+
console dependency is absent.
|
|
23
|
+
|
|
9
24
|
## [0.2.0] — 2026-06-23 — Early Access
|
|
10
25
|
|
|
11
26
|
### Added
|
|
@@ -75,5 +90,7 @@ tests, but the external code review + penetration test (the bar for a security-c
|
|
|
75
90
|
- Releases are built, SBOM'd (CycloneDX), and signed with [Sigstore](https://www.sigstore.dev/) — see the
|
|
76
91
|
`release` workflow.
|
|
77
92
|
|
|
78
|
-
[Unreleased]: https://github.com/wshallwshall/MessageFoundry/compare/v0.1
|
|
93
|
+
[Unreleased]: https://github.com/wshallwshall/MessageFoundry/compare/v0.2.1...HEAD
|
|
94
|
+
[0.2.1]: https://github.com/wshallwshall/MessageFoundry/compare/v0.2.0...v0.2.1
|
|
95
|
+
[0.2.0]: https://github.com/wshallwshall/MessageFoundry/compare/v0.1.0...v0.2.0
|
|
79
96
|
[0.1.0]: https://github.com/wshallwshall/MessageFoundry/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: messagefoundry
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Open-source healthcare integration engine — route, transform, and validate messages across many formats and connection types
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
License-File: LICENSE
|
|
@@ -60,7 +60,7 @@ from messagefoundry.parsing.message import Message, RawMessage
|
|
|
60
60
|
from messagefoundry.parsing.split import split_by_obr
|
|
61
61
|
from messagefoundry.timezone import convert_hl7_timestamp, to_zone
|
|
62
62
|
|
|
63
|
-
__version__ = "0.2.
|
|
63
|
+
__version__ = "0.2.1"
|
|
64
64
|
|
|
65
65
|
__all__ = [
|
|
66
66
|
"Message",
|
|
@@ -30,6 +30,21 @@ from messagefoundry.logging_setup import LOG_LEVELS, SyslogForward, configure_lo
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def main(argv: list[str] | None = None) -> int:
|
|
33
|
+
# Harden the human-facing streams for a legacy Windows codepage (cp1252/charmap): argparse's own
|
|
34
|
+
# --help/usage printer and runtime log/print() lines bypass _safe_print, so a non-cp1252 char
|
|
35
|
+
# (an arrow or other symbol in a help string or log line) would otherwise abort with
|
|
36
|
+
# UnicodeEncodeError. errors="replace" is lossy for such chars, but the machine-read JSON
|
|
37
|
+
# subcommands stay ASCII (json.dumps ensure_ascii=True). Guarded: some stream wrappers
|
|
38
|
+
# (PYTHONLEGACYWINDOWSSTDIO, pytest capture) lack reconfigure or reject it, and the hardening
|
|
39
|
+
# must never itself crash the CLI.
|
|
40
|
+
for _stream in (sys.stdout, sys.stderr):
|
|
41
|
+
_reconfigure = getattr(_stream, "reconfigure", None)
|
|
42
|
+
if _reconfigure is not None:
|
|
43
|
+
try:
|
|
44
|
+
_reconfigure(errors="replace")
|
|
45
|
+
except (ValueError, OSError):
|
|
46
|
+
pass
|
|
47
|
+
|
|
33
48
|
parser = argparse.ArgumentParser(prog="messagefoundry", description=__doc__)
|
|
34
49
|
parser.add_argument("--version", action="version", version=f"messagefoundry {__version__}")
|
|
35
50
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
@@ -111,8 +126,8 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
111
126
|
|
|
112
127
|
adr_analyze = sub.add_parser(
|
|
113
128
|
"adr-analyze",
|
|
114
|
-
help="advisory spec-driven ADR coverage: acceptance-criteria
|
|
115
|
-
"open clarifications (Secure Development Standards
|
|
129
|
+
help="advisory spec-driven ADR coverage: acceptance-criteria->test links, missing criteria, "
|
|
130
|
+
"open clarifications (Secure Development Standards section 5)",
|
|
116
131
|
)
|
|
117
132
|
adr_analyze.add_argument(
|
|
118
133
|
"--adr-dir", default="docs/adr", help="ADR directory (default: docs/adr)"
|
|
@@ -458,7 +473,7 @@ def _serve(args: argparse.Namespace) -> int:
|
|
|
458
473
|
# Only announce forwarding when configure_logging actually installed the handler — a TCP
|
|
459
474
|
# collector that is down at startup is skipped (it warns), so this must not contradict it.
|
|
460
475
|
logging.getLogger(__name__).info(
|
|
461
|
-
"off-box log forwarding enabled
|
|
476
|
+
"off-box log forwarding enabled -> %s:%d (%s, %s)",
|
|
462
477
|
log_forward.host,
|
|
463
478
|
log_forward.port,
|
|
464
479
|
log_forward.protocol,
|
|
@@ -81,6 +81,8 @@ from messagefoundry.api.models import (
|
|
|
81
81
|
ReloadRequest,
|
|
82
82
|
ReloadResult,
|
|
83
83
|
ReplayResult,
|
|
84
|
+
StatsResetRequest,
|
|
85
|
+
StatsResetResult,
|
|
84
86
|
StatsResponse,
|
|
85
87
|
SystemStatus,
|
|
86
88
|
)
|
|
@@ -565,9 +567,9 @@ def create_app(
|
|
|
565
567
|
_user: Identity = Depends(require(Permission.MONITORING_READ)),
|
|
566
568
|
) -> list[ConnectionRow]:
|
|
567
569
|
now = time.time()
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
)
|
|
570
|
+
# Offset-adjusted: subtracts any operator stats-resets (in-memory baselines). Identical to the
|
|
571
|
+
# raw store metrics when nothing has been reset.
|
|
572
|
+
metrics = await engine.connection_metrics_view(now=now, rate_window=_RATE_WINDOW)
|
|
571
573
|
rows: list[ConnectionRow] = []
|
|
572
574
|
|
|
573
575
|
# A source row per inbound connection, and a destination row per (inbound → outbound)
|
|
@@ -855,6 +857,58 @@ def create_app(
|
|
|
855
857
|
cancelled = await engine.store.cancel_queued(None, name, top_only=(scope == "top"))
|
|
856
858
|
return PurgeResult(cancelled=cancelled)
|
|
857
859
|
|
|
860
|
+
@app.post("/statistics/reset", response_model=StatsResetResult)
|
|
861
|
+
async def reset_statistics(
|
|
862
|
+
req: StatsResetRequest,
|
|
863
|
+
engine: Engine = Depends(_get_engine),
|
|
864
|
+
identity: Identity = Depends(require(Permission.MONITORING_DIAGNOSE)),
|
|
865
|
+
) -> StatsResetResult:
|
|
866
|
+
"""Zero the connections-dashboard cumulative counters (inbound read/errored, outbound
|
|
867
|
+
written/dead) for the selected connections, or all of them. This moves an in-memory baseline —
|
|
868
|
+
message rows (the PHI/audit record) and the Prometheus ``/metrics`` counters are untouched, as
|
|
869
|
+
are live gauges (queue depth, ages)."""
|
|
870
|
+
inbound: list[str] = []
|
|
871
|
+
outbound: list[tuple[str, str]] = []
|
|
872
|
+
if req.all:
|
|
873
|
+
# "Reset all" spans every channel, so a channel-scoped user may not run it (mirror purge).
|
|
874
|
+
if identity.allowed_channels is not None:
|
|
875
|
+
await _audit_channel_denied(engine, identity, None)
|
|
876
|
+
raise HTTPException(403, "channel-scoped users cannot reset all statistics")
|
|
877
|
+
else:
|
|
878
|
+
for t in req.targets:
|
|
879
|
+
# Per-channel RBAC: a scoped user may reset only endpoints of their own inbound channels
|
|
880
|
+
# (a destination row is the channel_id->destination edge, so the same scope applies).
|
|
881
|
+
if identity.allowed_channels is not None and not identity.can_access_channel(
|
|
882
|
+
t.channel_id
|
|
883
|
+
):
|
|
884
|
+
await _audit_channel_denied(engine, identity, t.channel_id)
|
|
885
|
+
raise HTTPException(403, "connection is outside your channel scope")
|
|
886
|
+
if t.role == "source":
|
|
887
|
+
if t.channel_id not in inbound:
|
|
888
|
+
inbound.append(t.channel_id)
|
|
889
|
+
else:
|
|
890
|
+
if t.destination is None:
|
|
891
|
+
raise HTTPException(422, "destination rows require a destination name")
|
|
892
|
+
key = (t.channel_id, t.destination)
|
|
893
|
+
if key not in outbound:
|
|
894
|
+
outbound.append(key)
|
|
895
|
+
count = await engine.reset_stats(
|
|
896
|
+
all_connections=req.all, inbound=inbound, outbound=outbound, now=time.time()
|
|
897
|
+
)
|
|
898
|
+
await engine.store.record_audit(
|
|
899
|
+
"stats_reset",
|
|
900
|
+
actor=identity.username,
|
|
901
|
+
detail=json.dumps(
|
|
902
|
+
{
|
|
903
|
+
"all": req.all,
|
|
904
|
+
"inbound": inbound,
|
|
905
|
+
"outbound": [list(k) for k in outbound],
|
|
906
|
+
"reset": count,
|
|
907
|
+
}
|
|
908
|
+
),
|
|
909
|
+
)
|
|
910
|
+
return StatsResetResult(reset=count)
|
|
911
|
+
|
|
858
912
|
# --- dead letters (verify + recover) -------------------------------------
|
|
859
913
|
|
|
860
914
|
@app.get("/dead-letters", response_model=DeadLetterList)
|
|
@@ -10,7 +10,7 @@ body (PHI) appears only in the single-message detail view, which is audited.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
-
from typing import Any
|
|
13
|
+
from typing import Any, Literal
|
|
14
14
|
|
|
15
15
|
from pydantic import BaseModel, Field
|
|
16
16
|
|
|
@@ -243,6 +243,26 @@ class ConnectionRow(BaseModel):
|
|
|
243
243
|
)
|
|
244
244
|
|
|
245
245
|
|
|
246
|
+
class StatsResetTarget(BaseModel):
|
|
247
|
+
"""One connections-dashboard endpoint to reset, matching a row's (role, channel_id, destination).
|
|
248
|
+
For ``source`` rows ``destination`` is ignored; for ``destination`` rows it is required."""
|
|
249
|
+
|
|
250
|
+
role: Literal["source", "destination"]
|
|
251
|
+
channel_id: str = Field(min_length=1, max_length=256)
|
|
252
|
+
destination: str | None = Field(default=None, max_length=256)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class StatsResetRequest(BaseModel):
|
|
256
|
+
"""Reset the dashboard's cumulative counters for ``targets``, or for every connection (``all``)."""
|
|
257
|
+
|
|
258
|
+
all: bool = False
|
|
259
|
+
targets: list[StatsResetTarget] = Field(default_factory=list)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class StatsResetResult(BaseModel):
|
|
263
|
+
reset: int # number of connection endpoints whose dashboard counters were reset
|
|
264
|
+
|
|
265
|
+
|
|
246
266
|
class StatsResponse(BaseModel):
|
|
247
267
|
outbox_by_status: dict[str, int]
|
|
248
268
|
# NOT-DONE rows (pending|inflight) across every stage (ingress + routed + outbound) — a
|
|
@@ -15,6 +15,21 @@ PySide6 unless you actually open the GUI.
|
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
from
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
# Static-only re-export: mypy --strict still resolves the names, but at runtime they load lazily
|
|
22
|
+
# via __getattr__ below, so importing this package (or find_spec'ing a sibling submodule like
|
|
23
|
+
# service_control) no longer hard-requires the [console] extra's httpx. Mirrors the
|
|
24
|
+
# lazy-truststore import already in client.py and the lazy-pydantic api/__init__ convention.
|
|
25
|
+
from messagefoundry.console.client import ApiError, EngineClient
|
|
19
26
|
|
|
20
27
|
__all__ = ["EngineClient", "ApiError"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def __getattr__(name: str) -> object:
|
|
31
|
+
if name in __all__:
|
|
32
|
+
from messagefoundry.console import client
|
|
33
|
+
|
|
34
|
+
return getattr(client, name)
|
|
35
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -15,7 +15,7 @@ from __future__ import annotations
|
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
17
|
import ssl
|
|
18
|
-
from collections.abc import Callable
|
|
18
|
+
from collections.abc import Callable, Sequence
|
|
19
19
|
from json import JSONDecodeError
|
|
20
20
|
from types import TracebackType
|
|
21
21
|
from typing import TypeVar
|
|
@@ -56,6 +56,7 @@ from messagefoundry.api.models import (
|
|
|
56
56
|
PurgeResult,
|
|
57
57
|
ReloadResult,
|
|
58
58
|
ReplayResult,
|
|
59
|
+
StatsResetResult,
|
|
59
60
|
StatsResponse,
|
|
60
61
|
SystemStatus,
|
|
61
62
|
)
|
|
@@ -375,6 +376,23 @@ class EngineClient:
|
|
|
375
376
|
PurgeResult,
|
|
376
377
|
)
|
|
377
378
|
|
|
379
|
+
def reset_stats(
|
|
380
|
+
self,
|
|
381
|
+
*,
|
|
382
|
+
all_connections: bool = False,
|
|
383
|
+
targets: Sequence[tuple[str, str, str | None]] = (),
|
|
384
|
+
) -> StatsResetResult:
|
|
385
|
+
"""Reset the connections-dashboard counters for ``targets`` (each ``(role, channel_id,
|
|
386
|
+
destination)``), or for every connection when ``all_connections`` is set."""
|
|
387
|
+
body = {
|
|
388
|
+
"all": all_connections,
|
|
389
|
+
"targets": [
|
|
390
|
+
{"role": role, "channel_id": channel_id, "destination": destination}
|
|
391
|
+
for (role, channel_id, destination) in targets
|
|
392
|
+
],
|
|
393
|
+
}
|
|
394
|
+
return _decode(self._request("POST", "/statistics/reset", json=body), StatsResetResult)
|
|
395
|
+
|
|
378
396
|
def list_messages(
|
|
379
397
|
self,
|
|
380
398
|
*,
|
|
@@ -127,6 +127,9 @@ class ConnectionsPage(QWidget):
|
|
|
127
127
|
menu.addSeparator()
|
|
128
128
|
act_purge_top = menu.addAction("Purge Top Message")
|
|
129
129
|
act_purge_all = menu.addAction("Purge All Queued Messages")
|
|
130
|
+
menu.addSeparator()
|
|
131
|
+
act_reset_sel = menu.addAction("Reset Statistics (Selected)")
|
|
132
|
+
act_reset_all = menu.addAction("Reset All Statistics")
|
|
130
133
|
self._actions.setMenu(menu)
|
|
131
134
|
|
|
132
135
|
self._start.clicked.connect(lambda: self._inbound_action(self._client.start_connection))
|
|
@@ -134,6 +137,8 @@ class ConnectionsPage(QWidget):
|
|
|
134
137
|
act_restart.triggered.connect(lambda: self._inbound_action(self._client.restart_connection))
|
|
135
138
|
act_purge_top.triggered.connect(lambda: self._purge("top"))
|
|
136
139
|
act_purge_all.triggered.connect(lambda: self._purge("all"))
|
|
140
|
+
act_reset_sel.triggered.connect(lambda: self._reset_stats(all_connections=False))
|
|
141
|
+
act_reset_all.triggered.connect(lambda: self._reset_stats(all_connections=True))
|
|
137
142
|
|
|
138
143
|
toolbar = QHBoxLayout()
|
|
139
144
|
toolbar.addWidget(QLabel("Connections"))
|
|
@@ -292,7 +297,10 @@ class ConnectionsPage(QWidget):
|
|
|
292
297
|
has = bool(self._selected_keys())
|
|
293
298
|
self._start.setEnabled(has)
|
|
294
299
|
self._stop.setEnabled(has)
|
|
295
|
-
|
|
300
|
+
# The Actions menu stays enabled even with no selection: "Reset All Statistics" needs none. The
|
|
301
|
+
# selection-dependent items (Restart / Purge / Reset Selected) guard themselves and report when
|
|
302
|
+
# nothing is selected.
|
|
303
|
+
self._actions.setEnabled(True)
|
|
296
304
|
|
|
297
305
|
# --- actions -------------------------------------------------------------
|
|
298
306
|
|
|
@@ -343,6 +351,36 @@ class ConnectionsPage(QWidget):
|
|
|
343
351
|
return
|
|
344
352
|
self.refresh()
|
|
345
353
|
|
|
354
|
+
def _reset_stats(self, *, all_connections: bool) -> None:
|
|
355
|
+
"""Zero the dashboard's cumulative counters (read / errored / written) for the selected rows,
|
|
356
|
+
or for every connection. Non-destructive: it moves a display baseline on the engine — messages
|
|
357
|
+
and history are untouched — so only "Reset All" is confirmed (it's broad)."""
|
|
358
|
+
targets: list[tuple[str, str, str | None]] = []
|
|
359
|
+
if all_connections:
|
|
360
|
+
answer = QMessageBox.question(
|
|
361
|
+
self,
|
|
362
|
+
"Reset all statistics",
|
|
363
|
+
"Reset the counters (read / errored / written) for ALL connections?\n\n"
|
|
364
|
+
"This only clears the dashboard tallies — messages and history are untouched.",
|
|
365
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
366
|
+
QMessageBox.StandardButton.No,
|
|
367
|
+
)
|
|
368
|
+
if answer != QMessageBox.StandardButton.Yes:
|
|
369
|
+
return
|
|
370
|
+
else:
|
|
371
|
+
# Each row key is (role, channel_id, dest|""); "" (source rows) becomes None for the API.
|
|
372
|
+
for role, channel_id, dest in self._selected_keys():
|
|
373
|
+
targets.append((role, channel_id, dest or None))
|
|
374
|
+
if not targets:
|
|
375
|
+
self.error.emit("Select one or more rows to reset, or use Reset All Statistics.")
|
|
376
|
+
return
|
|
377
|
+
try:
|
|
378
|
+
self._client.reset_stats(all_connections=all_connections, targets=targets)
|
|
379
|
+
except ApiError as exc:
|
|
380
|
+
self.error.emit(str(exc))
|
|
381
|
+
return
|
|
382
|
+
self.refresh()
|
|
383
|
+
|
|
346
384
|
def _on_cell_clicked(self, row: int, col: int) -> None:
|
|
347
385
|
if col != _LOGS_COL:
|
|
348
386
|
return
|
|
@@ -13,6 +13,7 @@ import asyncio
|
|
|
13
13
|
import logging
|
|
14
14
|
import time
|
|
15
15
|
from collections.abc import Callable, Mapping, Sequence
|
|
16
|
+
from dataclasses import replace
|
|
16
17
|
from pathlib import Path
|
|
17
18
|
from typing import Any
|
|
18
19
|
|
|
@@ -42,6 +43,7 @@ from messagefoundry.pipeline.retention import RetentionRunner
|
|
|
42
43
|
from messagefoundry.pipeline.state_convergence import StateConvergenceRunner
|
|
43
44
|
from messagefoundry.pipeline.wiring_runner import RegistryRunner
|
|
44
45
|
from messagefoundry.store import MessageStore, Store
|
|
46
|
+
from messagefoundry.store.store import ConnectionMetrics, DestinationMetrics, InboundMetrics
|
|
45
47
|
|
|
46
48
|
__all__ = ["Engine", "ConfigReloadDenied"]
|
|
47
49
|
|
|
@@ -180,6 +182,15 @@ class Engine:
|
|
|
180
182
|
self._graph_reconcile_interval = 1.0
|
|
181
183
|
# Set when start() runs; the "since" for since-engine-start metric counts.
|
|
182
184
|
self.started_at: float = 0.0
|
|
185
|
+
# Console stats-reset baselines (in-memory; dropped on restart, like the counts they offset).
|
|
186
|
+
# When an operator resets a connection's dashboard stats, we snapshot its current cumulative
|
|
187
|
+
# counters here; the connections view subtracts the snapshot so the visible read/errored/
|
|
188
|
+
# written/dead zero out without touching any message rows (the PHI/audit record). Keyed by
|
|
189
|
+
# channel_id (inbound) and (channel_id, destination) (outbound). See reset_stats().
|
|
190
|
+
self._inbound_stat_offsets: dict[str, tuple[int, int]] = {} # cid -> (read, errored)
|
|
191
|
+
self._outbound_stat_offsets: dict[
|
|
192
|
+
tuple[str, str], tuple[int, int]
|
|
193
|
+
] = {} # key -> (written, dead)
|
|
183
194
|
# The startup config dir is the default reload target and an implicit allowed root.
|
|
184
195
|
self.config_dir: Path | None = Path(config_dir).resolve() if config_dir else None
|
|
185
196
|
roots = [Path(r).resolve() for r in config_reload_roots]
|
|
@@ -712,6 +723,83 @@ class Engine:
|
|
|
712
723
|
self._registry_runner.notify_work()
|
|
713
724
|
return requeued
|
|
714
725
|
|
|
726
|
+
# --- connections-dashboard stats (in-memory reset baselines) -------------
|
|
727
|
+
|
|
728
|
+
async def connection_metrics_view(
|
|
729
|
+
self, *, now: float | None = None, rate_window: float = 60.0
|
|
730
|
+
) -> ConnectionMetrics:
|
|
731
|
+
"""Per-connection metrics for the dashboard with operator stats-resets applied. The cumulative
|
|
732
|
+
counters (inbound read/errored, outbound written/dead) have their reset baseline subtracted
|
|
733
|
+
(clamped at ``>= 0``); live gauges (queue depth, ages, last-seen) pass through untouched. With
|
|
734
|
+
no resets active this returns the store metrics verbatim, so the dashboard is byte-identical to
|
|
735
|
+
before this feature."""
|
|
736
|
+
metrics = await self.store.connection_metrics(
|
|
737
|
+
since=self.started_at, now=now, rate_window=rate_window
|
|
738
|
+
)
|
|
739
|
+
if not self._inbound_stat_offsets and not self._outbound_stat_offsets:
|
|
740
|
+
return metrics # fast path: nothing reset
|
|
741
|
+
inbound = {cid: self._apply_inbound_offset(cid, m) for cid, m in metrics.inbound.items()}
|
|
742
|
+
destinations = {
|
|
743
|
+
key: self._apply_outbound_offset(key, m) for key, m in metrics.destinations.items()
|
|
744
|
+
}
|
|
745
|
+
return ConnectionMetrics(inbound=inbound, destinations=destinations)
|
|
746
|
+
|
|
747
|
+
def _apply_inbound_offset(self, channel_id: str, m: InboundMetrics) -> InboundMetrics:
|
|
748
|
+
off = self._inbound_stat_offsets.get(channel_id)
|
|
749
|
+
if off is None:
|
|
750
|
+
return m
|
|
751
|
+
read0, errored0 = off
|
|
752
|
+
return replace(m, read=max(0, m.read - read0), errored=max(0, m.errored - errored0))
|
|
753
|
+
|
|
754
|
+
def _apply_outbound_offset(
|
|
755
|
+
self, key: tuple[str, str], m: DestinationMetrics
|
|
756
|
+
) -> DestinationMetrics:
|
|
757
|
+
off = self._outbound_stat_offsets.get(key)
|
|
758
|
+
if off is None:
|
|
759
|
+
return m
|
|
760
|
+
written0, dead0 = off
|
|
761
|
+
return replace(m, written=max(0, m.written - written0), dead=max(0, m.dead - dead0))
|
|
762
|
+
|
|
763
|
+
async def reset_stats(
|
|
764
|
+
self,
|
|
765
|
+
*,
|
|
766
|
+
all_connections: bool = False,
|
|
767
|
+
inbound: Sequence[str] = (),
|
|
768
|
+
outbound: Sequence[tuple[str, str]] = (),
|
|
769
|
+
now: float | None = None,
|
|
770
|
+
) -> int:
|
|
771
|
+
"""Move the connections-dashboard "count from" mark to now for the targeted connections so the
|
|
772
|
+
visible cumulative counters (inbound read/errored, outbound written/dead) zero out. Implemented
|
|
773
|
+
as an in-memory snapshot of the current counts — message rows are never touched, and the
|
|
774
|
+
Prometheus ``/metrics`` counters (which must stay monotonic) are untouched too. ``all_connections``
|
|
775
|
+
resets every connection that has carried traffic. Returns the number of endpoints reset.
|
|
776
|
+
|
|
777
|
+
A connection with no traffic yet snapshots to ``(0, 0)``, which is correct: everything it sees
|
|
778
|
+
from here on arrives after the reset. Re-resetting overwrites the snapshot with the live counts,
|
|
779
|
+
so it re-zeroes."""
|
|
780
|
+
# Snapshot the RAW store counts (no offsets) so a re-reset captures the live cumulative value.
|
|
781
|
+
metrics = await self.store.connection_metrics(since=self.started_at, now=now)
|
|
782
|
+
count = 0
|
|
783
|
+
if all_connections:
|
|
784
|
+
for cid, m in metrics.inbound.items():
|
|
785
|
+
self._inbound_stat_offsets[cid] = (m.read, m.errored)
|
|
786
|
+
count += 1
|
|
787
|
+
for key, dm in metrics.destinations.items():
|
|
788
|
+
self._outbound_stat_offsets[key] = (dm.written, dm.dead)
|
|
789
|
+
count += 1
|
|
790
|
+
return count
|
|
791
|
+
for cid in inbound:
|
|
792
|
+
im = metrics.inbound.get(cid)
|
|
793
|
+
self._inbound_stat_offsets[cid] = (im.read, im.errored) if im is not None else (0, 0)
|
|
794
|
+
count += 1
|
|
795
|
+
for key in outbound:
|
|
796
|
+
dmet = metrics.destinations.get(key)
|
|
797
|
+
self._outbound_stat_offsets[key] = (
|
|
798
|
+
(dmet.written, dmet.dead) if dmet is not None else (0, 0)
|
|
799
|
+
)
|
|
800
|
+
count += 1
|
|
801
|
+
return count
|
|
802
|
+
|
|
715
803
|
async def stop(self) -> None:
|
|
716
804
|
"""Stop the retention task + the wired graph, then close the store."""
|
|
717
805
|
log.info("engine stopping")
|
|
@@ -196,7 +196,13 @@ def check_console_importable() -> CheckResult:
|
|
|
196
196
|
|
|
197
197
|
def check_console_no_window() -> CheckResult:
|
|
198
198
|
"""The console's service-control path passes CREATE_NO_WINDOW (no console flash on Status poll)."""
|
|
199
|
-
|
|
199
|
+
try:
|
|
200
|
+
# find_spec on a SUBMODULE imports the parent package; if console/__init__ ever drags a
|
|
201
|
+
# missing [console]-extra dep (e.g. httpx) this raises ModuleNotFoundError. Degrade to SKIP
|
|
202
|
+
# like every sibling check instead of crashing the whole `verify` run on a non-[console] box.
|
|
203
|
+
spec = importlib.util.find_spec("messagefoundry.console.service_control")
|
|
204
|
+
except (ImportError, ValueError):
|
|
205
|
+
spec = None
|
|
200
206
|
if spec is None or not spec.origin:
|
|
201
207
|
return CheckResult(
|
|
202
208
|
"host.noflash",
|
|
@@ -5,6 +5,8 @@ fail-closed leak-check — engine side."""
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
8
10
|
import pytest
|
|
9
11
|
|
|
10
12
|
from messagefoundry.anon import (
|
|
@@ -22,6 +24,15 @@ from messagefoundry.anon import (
|
|
|
22
24
|
)
|
|
23
25
|
from messagefoundry.anon.surrogates import Seps, scrub_site_codes, surrogate_field
|
|
24
26
|
|
|
27
|
+
# The leak-check delegates to scripts/publish/scan_forbidden.py (the owner-managed publish guard — a
|
|
28
|
+
# dev/source-checkout tool, not in the wheel and deny-listed in the OSS mirror). Skip the two tests that
|
|
29
|
+
# exercise it where it's absent; the engine raises LeakCheckUnavailable there by design.
|
|
30
|
+
_LEAK_SCANNER = Path(__file__).resolve().parents[1] / "scripts" / "publish" / "scan_forbidden.py"
|
|
31
|
+
_NO_SCANNER = pytest.mark.skipif(
|
|
32
|
+
not _LEAK_SCANNER.exists(),
|
|
33
|
+
reason="leak-check needs scripts/publish/scan_forbidden.py (private-only; OSS-mirror deny-list)",
|
|
34
|
+
)
|
|
35
|
+
|
|
25
36
|
_SALT = "unit-salt-0123456789abcdef"
|
|
26
37
|
_SEPS = Seps()
|
|
27
38
|
|
|
@@ -184,6 +195,7 @@ def test_anonymize_reads_custom_separators_from_msh() -> None:
|
|
|
184
195
|
# --- leak-check -----------------------------------------------------------------------------------
|
|
185
196
|
|
|
186
197
|
|
|
198
|
+
@_NO_SCANNER
|
|
187
199
|
def test_leak_check_clean_and_dirty() -> None:
|
|
188
200
|
assert leak_check(anonymize(_SAMPLE, salt=_SALT)) == []
|
|
189
201
|
hits = leak_check("note mentioning OMNICELL and 540099")
|
|
@@ -191,6 +203,7 @@ def test_leak_check_clean_and_dirty() -> None:
|
|
|
191
203
|
assert any("54" in h for h in hits)
|
|
192
204
|
|
|
193
205
|
|
|
206
|
+
@_NO_SCANNER
|
|
194
207
|
def test_anonymize_checked_fails_closed_and_is_phi_safe() -> None:
|
|
195
208
|
# estate token in a KEPT field (MSH-3) survives surrogation -> must raise
|
|
196
209
|
dirty = _msg(
|
|
@@ -38,6 +38,11 @@ _REFUSED = ["", "PID|1||9^^^H^MR||DOE^JOHN", "MSH|^~|A|B", "not hl7 at all"]
|
|
|
38
38
|
|
|
39
39
|
def _load_scan_forbidden() -> object:
|
|
40
40
|
path = _ROOT / "scripts" / "publish" / "scan_forbidden.py"
|
|
41
|
+
if not path.exists():
|
|
42
|
+
# Private-only (scripts/publish/ is deny-listed in the OSS mirror); skip where it's absent.
|
|
43
|
+
pytest.skip(
|
|
44
|
+
"scan_forbidden.py is private-only (OSS-mirror deny-list)", allow_module_level=True
|
|
45
|
+
)
|
|
41
46
|
spec = importlib.util.spec_from_file_location("scan_forbidden", path)
|
|
42
47
|
assert spec is not None and spec.loader is not None
|
|
43
48
|
mod = importlib.util.module_from_spec(spec)
|
|
@@ -40,6 +40,24 @@ def test_validate_clean_sample(capsys: pytest.CaptureFixture[str]) -> None:
|
|
|
40
40
|
assert _out_json(capsys) == []
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
def test_top_level_help_encodes_on_legacy_windows_codepage(
|
|
44
|
+
capsys: pytest.CaptureFixture[str],
|
|
45
|
+
) -> None:
|
|
46
|
+
# Regression: `messagefoundry --help` crashed with UnicodeEncodeError on a cp1252/charmap
|
|
47
|
+
# console because of a U+2192 arrow in the adr-analyze subparser help. Render the help string
|
|
48
|
+
# in-process and assert it survives a cp1252 encode -- reproduces the Windows-only crash on any
|
|
49
|
+
# runner without touching the real terminal (argparse --help raises SystemExit after printing).
|
|
50
|
+
with pytest.raises(SystemExit):
|
|
51
|
+
main(["--help"])
|
|
52
|
+
help_text = capsys.readouterr().out
|
|
53
|
+
assert "adr-analyze" in help_text, "top-level help did not render the subcommand list"
|
|
54
|
+
try:
|
|
55
|
+
help_text.encode("cp1252")
|
|
56
|
+
except UnicodeEncodeError as exc:
|
|
57
|
+
bad = help_text[exc.start]
|
|
58
|
+
pytest.fail(f"top-level --help is not cp1252-encodable: U+{ord(bad):04X} {bad!r}")
|
|
59
|
+
|
|
60
|
+
|
|
43
61
|
def test_validate_reports_problems(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
|
|
44
62
|
(tmp_path / "bad.py").write_text("raise ValueError('boom')\n", encoding="utf-8")
|
|
45
63
|
assert main(["validate", "--config", str(tmp_path), "--json"]) == 1
|