Architecture

How MessageFoundry fits together

Three views, each answering a different question: what the components are and where the process boundaries sit; how a received message moves through the durable staged queue and earns a disposition; and how Connections, Routers, and Handlers wire together by name. The prose source of truth is the engine's ARCHITECTURE.md.

1 · Components & boundaries

System topology

The engine is a headless service; clients are separate processes that reach it only through the localhost API. Dependencies point one way — the API depends on the engine, the engine never imports the API or a client.

System topology The admin console, VS Code extension, and test harness reach the engine only through a localhost API with auth and RBAC. The headless engine's pipeline depends on transports, parsing, the store (SQLite, PostgreSQL, SQL Server), and config. depends on over the API / wire Admin console separate process VS Code extension authoring + ops Test harness synthetic traffic LOCALHOST · THE ONLY EXTERNAL SURFACE API — HTTP + WebSocket auth · RBAC · hash-chained audit ENGINE — HEADLESS ASYNCIO SERVICE Pipeline listener · router · transform · delivery Transports MLLP · TCP · HTTP SOAP · DB · files (SFTP/FTP/FTPS) Parsing HL7 v2 deep parse; JSON / XML / X12 routed Store SQLite · PostgreSQL · SQL Server AES-256-GCM Config Connections · Routers · Handlers
2 · Runtime message flow

The durable staged queue

A received message is ACKed on receipt — once it's durably committed to the ingress stage, before routing, transform, or delivery. Each handoff is a single committed transaction, giving at-least-once delivery, retries, and replay with no separate broker.

Runtime message flow through the staged queue An inbound message is decoded and parsed by the listener, committed to the ingress stage, and ACKed on receipt. It then moves through routed and outbound stages via committed transactions — router, transform, and delivery workers — before reaching the outbound connection. Each message earns a disposition finalized by the store. listener router transform deliver ACK (AA) — on receipt Inbound connection ingress raw committed routed one row / handler outbound one row / dest. Outbound idempotent send DISPOSITION · count-and-log, finalized by the store decode/validate failures NAK synchronously, pre-ingress RECEIVED → ROUTED / UNROUTED → PROCESSED / FILTERED / ERROR
3 · Config wiring

Connections, Routers, and Handlers — wired by name

An inbound Connection names a Router; the Router forwards to Handler(s) by name; each Handler sends to outbound Connection(s). There's no enclosing "channel" object — set it up with guided wizards, or write it in Python.

Config wiring graph An inbound connection IB_ACME_ADT (MLLP) names a router. The router forwards by name to two handlers — to_EHR and to_archive — which Send to outbound connections OB_EHR_ADT (MLLP) and OB_ARCHIVE (File). names by name Send Send IB_ACME_ADT inbound · MLLP @router filters · forwards by name @handler: to_EHR filter → transform @handler: to_archive filter → transform OB_EHR_ADT outbound · MLLP OB_ARCHIVE outbound · File

See it run for yourself

From install to your first routed message — with the full feature set and the engine docs a click away.