Metadata-Version: 2.5
Name: messagefoundry
Version: 0.4.0
Summary: Open-source healthcare integration engine — route, transform, and validate messages across many formats and connection types
Project-URL: Homepage, https://messagefoundry.org/
Project-URL: Documentation, https://messagefoundry.org/
Project-URL: Repository, https://github.com/MEFORORG/MessageFoundry
Project-URL: Issues, https://github.com/MEFORORG/MessageFoundry/issues
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
License-File: NOTICE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Communications
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: System :: Networking
Classifier: Typing :: Typed
Requires-Python: >=3.14
Requires-Dist: aiosqlite>=0.20
Requires-Dist: annotated-types<0.8
Requires-Dist: argon2-cffi>=23.1
Requires-Dist: cryptography>=48.0.1
Requires-Dist: defusedxml>=0.7.1
Requires-Dist: fastapi>=0.137.1
Requires-Dist: hl7>=0.4.5
Requires-Dist: hl7apy>=1.3
Requires-Dist: httpx>=0.27
Requires-Dist: ldap3>=2.9
Requires-Dist: prometheus-client>=0.20
Requires-Dist: psutil>=6.0
Requires-Dist: pydantic>=2.6
Requires-Dist: pyspnego>=0.10
Requires-Dist: starlette>=1.3.1
Requires-Dist: tomlkit>=0.12
Requires-Dist: truststore>=0.10
Requires-Dist: tzdata>=2024.1
Requires-Dist: uvicorn[standard]>=0.29
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.26; extra == 'dev'
Requires-Dist: pytest-rerunfailures>=16.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.3; extra == 'dev'
Requires-Dist: pytest-xdist>=3.6; extra == 'dev'
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Requires-Dist: ruff<0.16,>=0.4; extra == 'dev'
Provides-Extra: dicom
Requires-Dist: pydicom<4,>=3.0.2; extra == 'dicom'
Requires-Dist: pynetdicom<4,>=3.0.4; extra == 'dicom'
Provides-Extra: fhir
Requires-Dist: annotated-types<0.8; extra == 'fhir'
Requires-Dist: fhir-resources>=7.1.0; extra == 'fhir'
Requires-Dist: fhirpathpy>=2.2.0; extra == 'fhir'
Provides-Extra: fuzz
Requires-Dist: atheris>=3.1.0; (sys_platform == 'linux' and platform_machine == 'x86_64') and extra == 'fuzz'
Provides-Extra: harness
Requires-Dist: pyside6>=6.6; extra == 'harness'
Provides-Extra: otel
Requires-Dist: opentelemetry-exporter-otlp>=1.20; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'otel'
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.29; extra == 'postgres'
Provides-Extra: sftp
Requires-Dist: paramiko>=5.0; extra == 'sftp'
Provides-Extra: sqlserver
Requires-Dist: aioodbc>=0.5; extra == 'sqlserver'
Provides-Extra: vault
Requires-Dist: hvac<3,>=2.3.0; extra == 'vault'
Provides-Extra: webauthn
Requires-Dist: webauthn<4,>=3.0.0; extra == 'webauthn'
Provides-Extra: x12
Requires-Dist: pyx12>=4.0.0; extra == 'x12'
Provides-Extra: xml
Requires-Dist: lxml>=6.0.0; extra == 'xml'
Requires-Dist: signxml>=4.0.0; extra == 'xml'
Requires-Dist: xmlschema>=4.0.0; extra == 'xml'
Description-Content-Type: text/markdown

# MessageFoundry

[![CI](https://github.com/MEFORORG/MessageFoundry/actions/workflows/ci.yml/badge.svg)](https://github.com/MEFORORG/MessageFoundry/actions/workflows/ci.yml)
[![Security](https://github.com/MEFORORG/MessageFoundry/actions/workflows/security.yml/badge.svg)](https://github.com/MEFORORG/MessageFoundry/actions/workflows/security.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://github.com/MEFORORG/MessageFoundry/blob/main/LICENSE)
[![Python 3.14+](https://img.shields.io/badge/python-3.14%2B-blue.svg)](https://github.com/MEFORORG/MessageFoundry/blob/main/pyproject.toml)

**Website & documentation: [messagefoundry.org](https://messagefoundry.org/)** ·
**[Changelog](https://github.com/MEFORORG/MessageFoundry/blob/main/CHANGELOG.md)**

MessageFoundry is an **open-source healthcare integration engine** — a modern, Python-native HL7
interface engine. It connects clinical and business systems by routing, transforming, and validating
messages across many formats (HL7 v2, JSON, XML/SOAP, X12, database records) and connection types
(MLLP, MLLP-over-TLS, TCP, HTTP/REST, SOAP, FHIR, DICOM, database, files, SFTP/FTP). Configure it with
guided tooling or extend it in Python; it runs on SQLite, PostgreSQL, or SQL Server with
authentication, RBAC, audit logging, and encryption-at-rest built in.

> Python import package: `messagefoundry`. Built with **hl7apy** + **python-hl7** (HL7 parsing/
> validation), **FastAPI** (engine API + the same-origin `/ui` web console), and **PySide6** (the
> standalone test harness).

## What it is

A modern alternative to engines like Mirth and Corepoint. Messages flow through a graph you
wire by name: an inbound **Connection** hands off to a **Router**, which forwards to one or more
**Handlers** (filter → transform), which deliver to outbound Connections — all backed by durable
queuing, automatic retries, and replay. Build that graph with guided wizards, or in Python for full
control; either way the configuration is version-controlled and yours.

## Architecture

**Engine-as-library + localhost API.** The engine is an importable Python package.
A browser **web console** (served same-origin at `/ui`) talks to it over a localhost HTTP + WebSocket
API — the same way whether the engine runs in-process, as a local daemon, or (later) on a remote host.
No hand-rolled IPC; the deployment split is a config choice, not an architectural fork.

See **[docs/architecture-diagram.md](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/architecture-diagram.md)** for the rendered diagrams —
system topology, runtime message flow through the staged queue, and the config wiring graph (Mermaid,
renders on GitHub and in the VS Code preview). The prose source of truth is
[docs/ARCHITECTURE.md](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/ARCHITECTURE.md).

### Key decisions
- **Reliable by default.** A durable, transactional pipeline gives at-least-once delivery,
  automatic retries, replay, and dead-lettering — no separate message broker to run.
- **Async core.** asyncio with per-connection workers for listeners, pollers, retries.
- **Tolerant parsing first.** `python-hl7` for fast routing/peek; `hl7apy` for deep,
  version-aware validation and profiles on demand (real-world HL7 is often non-conformant).
- **Configure visually or in code.** Author connections and routes with guided wizards, or in
  Python (`inbound`/`outbound`/`@router`/`@handler`) for full control — always version-controlled.
  The database holds runtime state and messages only, never configuration.
- **PHI is first-class.** Authentication, RBAC, a user-attributed audit log of message
  views/replays, **encryption-at-rest** for message bodies (AES-256-GCM), **global PHI log redaction**,
  and **transport TLS** (HTTPS/WSS for the API plus MLLP-over-TLS) are **built**; MFA and off-box log
  shipping remain on the roadmap. See [docs/PHI.md](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/PHI.md) for the full data-protection map.

## Features

MessageFoundry ships a reliable, PHI-aware engine today: the Connection/Router/Handler graph
over a durable staged pipeline (at-least-once delivery, retries, dead-letter, replay), backed by
SQLite, PostgreSQL, or SQL Server. It speaks MLLP (plain and over TLS), file/SFTP, REST, SOAP,
FHIR, database, and DICOM (C-STORE SCP), parses HL7 v2 tolerantly (with opt-in strict validation)
and carries other formats payload-agnostically (JSON, XML/SOAP, X12, binary). Security is
first-class — authentication, RBAC, a user-attributed audit log, at-rest body encryption, and
transport TLS — and it runs single-node or in active-passive high availability.

**See the full, up-to-date feature breakdown — built vs. planned — at
[messagefoundry.org/features-table.html](https://messagefoundry.org/features-table.html).**

## Documentation

Full documentation lives on **[messagefoundry.org](https://messagefoundry.org/)**:

- **[Mental map](https://messagefoundry.org/assets/docs/MessageFoundry-Mental-Model.pdf)** — an
  orientation guide to how the pieces fit: Connections → Router → Handlers → Connections, with the
  headless engine and the web console/IDE that drive it.
- **[Install Guide](https://messagefoundry.org/assets/docs/MessageFoundry-Install-Guide.pdf)** — install,
  configure, secure, and roll out to production.
- **[User Guide](https://messagefoundry.org/assets/docs/MessageFoundry-User-Guide.pdf)** — author and
  operate interfaces day to day.

**Get started:** [Quickstart](https://messagefoundry.org/getting-started.html) ·
[Guides](https://messagefoundry.org/guides/) ·
[Documents](https://messagefoundry.org/documents.html)

**In this repository:** [`docs/README.md`](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/README.md)
is the index for the 377 documents under `docs/`. It opens with a six-step **start-here path for a new
operator**, then splits the rest by audience — operators, developers, security reviewers, maintainers —
and quarantines the dated planning artifacts so you do not mistake a superseded plan for instructions.

## Installing & rolling out

**The recommended way to deploy MessageFoundry is to install the published package from
[PyPI](https://pypi.org/project/messagefoundry/)** — a signed, version-pinned wheel is the
supported production artifact, with no source checkout required. Install it as a **pinned
dependency**, then scaffold your own config repo ([ADR 0017](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/adr/0017-consumer-deployment-model.md)):

```bash
pip install "messagefoundry==<version>"   # pin the exact engine version (core runtime, SQLite store)
messagefoundry init ./my-config-repo      # scaffold a standalone config repo
cd ./my-config-repo
messagefoundry serve --config config --env dev
```

MessageFoundry is in **Early Access**. Always **pin the exact version** so upgrades stay
deliberate — replace `<version>` with the current release shown at the top of the
[PyPI project page](https://pypi.org/project/messagefoundry/). Add the extras your deployment
needs (each is opt-in and lazy-imported):

```bash
pip install "messagefoundry[postgres]==<version>"    # PostgreSQL store backend (production server DB)
pip install "messagefoundry[sqlserver]==<version>"   # SQL Server store backend (+ OS-level ODBC Driver 18)
pip install "messagefoundry[sftp]==<version>"        # SFTP transport for the REMOTEFILE connector
pip install "messagefoundry[dicom]==<version>"       # DICOM codec + C-STORE SCP (pydicom + pynetdicom)
pip install "messagefoundry[harness]==<version>"     # the standalone PySide6 test harness GUI
```

**Web console 0.3.0 is the one that pairs with engine 0.4.0.** The browser console (`/ui`) ships as
its own wheel, `messagefoundry-webconsole`, with its own version numbers. It does not share the
engine's version, so `messagefoundry-webconsole==0.4.0` does not exist. The engine mounts a console
only if it was built against this engine's UI seam, the version of the interface between the two.
Console 0.3.0 was built against engine 0.4.0's seam. It is published alongside engine 0.4.0, under
its own `webconsole-v0.3.0` tag. Pin the pair: `messagefoundry==0.4.0` with
`messagefoundry-webconsole==0.3.0`. Without that console, engine 0.4.0 behaves like this:

- **No console installed:** the engine serves the JSON API only and prints a warning at startup. If you
  set `[security].serve_web_console = true`, it refuses to start instead.
- **Console 0.2.15 installed, console on:** the engine refuses to start. 0.2.15 was built for an older
  engine, so startup stops with an import error or a seam mismatch. The console is on by default for a
  loopback bind. Upgrade the console to 0.3.0, or set `[security].serve_web_console = false`.

**What's in the `messagefoundry` package — and what isn't.** It is the **engine**; the operator UI is
the browser **web console** served same-origin at `/ui`, which ships as a separate wheel
(`messagefoundry-webconsole`) with its own version, so a headless server, container, or adopter
install stays lean. The engine mounts the console in-process, and the console must match the engine's
UI seam (see above); `[security].serve_web_console` turns it on or off. (The former PySide6 desktop
console was retired in favour of the web console — BACKLOG #103; PySide6 now backs only the opt-in `[harness]` test
tooling.) The **VS Code extension is a separate product, not on PyPI** (a VS Code extension is a
different ecosystem); see *VS Code extension & test harness* below for where to get it.

> **Verify before you install (supply chain).** Every release is built by a GitHub Actions workflow
> and published with **PEP 740 attestations** — all three publish jobs set `attestations: true`.
>
> **Sigstore signing, SLSA build-provenance and the CycloneDX SBOM cover the ENGINE wheel only.** The
> `messagefoundry-webconsole` and `messagefoundry-harness` release jobs contain no signing, attestation
> or SBOM step (BACKLOG #1193) — this note previously said "every release", which is why it is spelled
> out per artifact rather than tightened in place. So `gh attestation verify` finds a GitHub
> attestation for the engine wheel and **will not** find one for the console or harness wheel; those
> carry the PyPI-side attestation only.
>
> Verify a downloaded **engine** wheel against its source commit with
> `gh attestation verify <wheel> --repo MEFORORG/MessageFoundry`, or pull the signed wheel + SBOM
> from the [GitHub Release assets](https://github.com/MEFORORG/MessageFoundry/releases). For an
> air-gapped site, mirror the wheel to a private index.
>
> *(Engine developers install from a checkout instead — see [Development](#development).)*

Piloting MessageFoundry? The **[Install Guide](https://messagefoundry.org/assets/docs/MessageFoundry-Install-Guide.pdf)**
takes you from first install through a staged, go/no-go-gated path to full production
(Lab → Shadow/Parallel → Limited → Full). It leads with an honest built-vs-experimental
maturity map and covers prerequisites, install, security/PHI hardening, reliability
configuration, validation, load testing, backup/DR, day-2 operations, and upgrade/rollback.

## Development

**Working on the engine itself?** Install from a source checkout — **editable**, with the dev tools.
(This is the contributor path; deployments install the pinned wheel, [above](#installing--rolling-out).)

```bash
python -m venv .venv && . .venv/Scripts/activate   # Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -e ".[dev]"
pytest
```

Run the engine + localhost API (loads the bundled sample config, which ships only in a checkout).
It refuses to start until its secure-by-default posture is met, starting with a store encryption
key (`messagefoundry gen-key`, set as `MEFOR_STORE_ENCRYPTION_KEY`). Each refusal names the setting
it needs; the [User Guide](https://github.com/MEFORORG/MessageFoundry/blob/main/docs/USER-GUIDE.md)
covers the key.

```bash
python -m messagefoundry serve --config samples/config --db messagefoundry.db --env dev
# API on https://127.0.0.1:8765 — GET /connections, /messages, /stats, WS /ws/stats
```

The engine always serves HTTPS. With no `[api].tls_cert_file` set, it mints a self-signed
certificate on first run and saves it beside the store database as `api-generated-cert.pem`. A
browser warns about that certificate, and other clients reject it, until you import it into the
trust store or configure your own. The one exception is a declared TLS-terminating proxy in front
(`[api].tls_terminated_upstream`): the engine then speaks plain HTTP to the proxy, and you browse to
the proxy's address.

Then open the admin console in a browser (install the web console alongside the engine with
`pip install -e packaging/messagefoundry-webconsole`; it is on by default for a loopback bind, so
there is no switch to set):

```bash
# browse to https://127.0.0.1:8765/ui and sign in
```

### VS Code extension & test harness

- **VS Code extension** ([`ide/`](https://github.com/MEFORORG/MessageFoundry/tree/main/ide/)) — author and test interfaces in your editor: a New Route
  Wizard, validate-on-save, a Test Bench (dry-run `.hl7` files with before/after diffs), Stage →
  Promote to a running engine, and an HL7-aware `@messagefoundry` chat participant. **It is not on PyPI**
  (a VS Code extension is a different ecosystem) **and not yet on the VS Code Marketplace** — Marketplace
  + Open VSX publishing is **planned** (the plan itself is not public — see
  [docs/BACKLOG.md](docs/BACKLOG.md)). Until then, get it from
  this repo: open the `ide/` folder in VS Code and press **F5** (Extension Development Host), or build the
  VSIX (`cd ide && npm install && npx @vscode/vsce package`) and install the `.vsix`. See
  [ide/README.md](https://github.com/MEFORORG/MessageFoundry/blob/main/ide/README.md).
- **Test harness** — synthetic-only send/receive (MLLP), load, and failover tooling for exercising a
  running engine. It ships as a **separate distribution, `messagefoundry-harness`**, released in lockstep
  with the engine (it is *not* in the engine wheel): `pip install messagefoundry-harness`, then
  `python -m harness`. From a checkout, run `python -m harness` directly. Synthetic, PHI-free traffic only.

## License

MessageFoundry is licensed under the **GNU Affero General Public License v3.0 or later**
(`AGPL-3.0-or-later`) — see [LICENSE](https://github.com/MEFORORG/MessageFoundry/blob/main/LICENSE). Running a modified version as a network service
triggers the AGPL's §13 source-offer obligation. A separately-licensed commercial edition is planned
by **MessageFoundry Foundation, LLC** under the standard open-core model — see
[COMMERCIAL-LICENSE.md](https://github.com/MEFORORG/MessageFoundry/blob/main/COMMERCIAL-LICENSE.md) (terms pending legal review). See [NOTICE](https://github.com/MEFORORG/MessageFoundry/blob/main/NOTICE)
for copyright and attribution.

## Contributing

Contributions are welcome — see [CONTRIBUTING.md](https://github.com/MEFORORG/MessageFoundry/blob/main/CONTRIBUTING.md), our
[Code of Conduct](https://github.com/MEFORORG/MessageFoundry/blob/main/CODE_OF_CONDUCT.md), and how the project is governed in [GOVERNANCE.md](https://github.com/MEFORORG/MessageFoundry/blob/main/GOVERNANCE.md).
A signed [Contributor License Agreement](https://github.com/MEFORORG/MessageFoundry/blob/main/CLA.md) is required before a pull request can be merged.
