Tenon is a satellite project of Apache BifroMQ (Incubating), connecting BifroMQ with external systems through MQTT client connections.
Tenon's plugin architecture is general-purpose. Source and Sink plugins can connect any systems for which suitable plugins are available, independently of BifroMQ.
See the incubation disclaimer.
Tenon combines typed plugins with Lua data processing. A standalone Runner manages installed plugin programs and declarative Tenon Documents. Each Document describes a Pipeline; its Flows read from Source instances, transform records in Lua, and write to Sink instances.
Source Plugin → Flow Channel / Lua → Sink Plugin ↑ Runner manages configuration, processes, packages and diagnostics
Write plugins in Rust or Java using the SDKs and project scaffolds. Start with the plugin development guide. Developers adding a language SDK and scaffold should use the SDK implementation contract.
Plugins run in separate processes. A plugin can implement Source, Sink, or both interfaces; both interfaces share one process and configuration when they belong to the same instance.
This repository contains the Runner, IPC implementations, SDKs, plugin generators, and an MQTT plugin.
The Rust toolchain is pinned in rust-toolchain.toml. Install Rust through rustup, a native C compiler and linker, and Python 3 with jsonschema==4.23.0 for contract checks. The Rust workspace builds its vendored Lua runtime and Protocol Buffers tools.
cargo build --locked --bin tenon python3 tools/validate-contracts.py python3 tools/validate-public-docs.py
Follow the local quickstart to generate a plugin from source, install it, run a Lua Flow, and verify a real output file. It does not require an external message broker or previously published Tenon artifacts.
Supported build targets are Linux and macOS on x86-64 and AArch64. macOS requires 14.4 or later. Platform names in plugin manifests are linux/darwin and amd64/arm64. A package must declare the target it actually supports; an accepted declaration does not verify external dependencies or connectivity.
Java development uses the Maven wrapper under sdk/java/ and the exact JDK recorded in tenon-toolchain.properties. See the Java SDK, Java plugin generator, Rust SDK, and Rust plugin scaffold.
A Program is an immutable installed package identified by its name and exact version. An Instance is one configured use of that Program. A Flow binds one Source instance to Lua and one or more Sink instances. A Channel processes records in order; parallel channels have independent Lua state.
The Runner saves Documents and installed packages across restarts. Saving a Document and applying it are separate outcomes. Use Pipeline status and its desired/applied ETags to see progress; local running status does not prove delivery to an external system.
Queues, Lua state and timers are volatile. Delivery completion follows the selected Flow policy and plugin behavior. Tenon does not provide a durable message log, distributed transactions, or end-to-end exactly-once delivery. See Documents and delivery before choosing replay and acknowledgement behavior.
Management write access grants control over executable workloads. The default Runner has no HTTP request authorization and stores Documents as plaintext; mTLS authenticates clients but does not assign operation permissions. Establish deployment access controls and review the security policy and threat model before exposing the API or accepting plugins and Documents.
Machine-readable schemas and shared test vectors live in contracts/. The running binary serves its own API description at /openapi.json and its Document Schema at /document-schema.
The source is licensed under Apache License 2.0. See NOTICE and the licenses shipped with dependencies and generated runtime bundles.