One dependency line.
Four surfaces. Feature-gated.
joule-comm
is the unified Rust SDK for CommunicationOS. Every surface — Engage,
Realtime, Fabric, Desktop — is a Cargo feature. Turn on only what you
use. The crate re-exports the underlying workspace modules under
canonical namespaces and ships a post-quantum-ready MLS
(RFC 9420) E2E layer out of the box.
1 · Install
Add to your Cargo.toml
[dependencies]
# everything
joule-comm = { version = "0.1", features = ["full"] }
# multi-channel send only
joule-comm = { version = "0.1", features = ["engage"] }
# post-quantum-ready E2E messaging only
joule-comm = { version = "0.1", features = ["mls"] }
# engage + E2E (typical fintech / healthcare customer)
joule-comm = { version = "0.1", features = ["engage", "mls"] } Build times scale with selected surfaces. Default features are empty (fastest build); the full feature set compiles in roughly 30 s on a modern dev machine.
Swift · iOS / macOS
// Package.swift
.package(url: "https://github.com/Transaction-Science/swift-moq.git", from: "0.3.0"),
.target(name: "MyApp", dependencies: [
.product(name: "JouleMoQ", package: "swift-moq"),
]), swift-moq is 1,207 LOC of Swift: native MoQT subscriber, BLAKE3 + Ed25519 verifier, WAI envelope unpack. Targets iOS 17 + and macOS 14 +. Full reference at /sdk/swift.
JavaScript / WASM · browsers
// vite / esbuild / webpack
import init, { Verifier } from "@transaction-science/joule-moq-wasm";
import { createDispatcher, verifyAndDispatch }
from "@transaction-science/joule-moq-wasm/wai-shim.js";
await init();
const v = new Verifier();
v.add_trust_anchor(publisherKeyBytes);
v.cache_group(groupReceiptJson);
const dispatcher = createDispatcher();
dispatcher.register("wai.audio.opus", async (env, verified) => { /* … */ }); joule-moq-wasm is 1,247 LOC. Browser Verifier + WAI envelope unpack (W3, shipped 2026-05-26). Self-contained — no tokio, no QUIC stack — keeps the wasm bundle lean.
1b · Languages
Three native shapes, one wire format
The Rust crate ships every surface. The Swift and WASM packages mirror the subscriber-side wire format so iOS / Vision Pro / browsers can verify signed frames without dragging in a full QUIC stack.
2 · Feature flags
What each feature unlocks
Native SDKs beyond Rust ship as separate crates: swift-moq (1,207 LOC Swift) for iOS / macOS, joule-moq-wasm (1,247 LOC) for browsers. See the install block below.
3 · Examples
What it looks like in code
Send a multi-channel message
use joule_comm::engage::{channels, sms, email};
let mut router = channels::ChannelRouter::new();
router.register_platform(Box::new(my_slack_adapter))?;
router.register_platform(Box::new(my_twilio_adapter))?;
let msg = channels::OutboundMessage::plain(
channels::Platform::Slack,
"C0123456789",
"Deploy 2026.4.3 succeeded.",
);
let receipt = router.send(msg)?;
// receipt.energy_uj is metered per-platform
// every delivery emits a JWP ReceiptPayload Create an MLS group, invite, encrypt
use joule_comm::mls::{Identity, GroupSession};
let alice = Identity::generate("alice");
let bob = Identity::generate("bob");
// Alice creates the group, adds Bob, hands Bob the welcome bytes out-of-band.
let mut alice_group = GroupSession::create(&alice)?;
let (welcome, add_receipt) =
alice_group.add_member(&alice, bob.key_package())?;
// Bob joins.
let mut bob_group = GroupSession::join(&bob, welcome)?;
// Alice encrypts, Bob decrypts.
let (ciphertext, send_receipt) =
alice_group.send(&alice, b"Merger is at 4.2x EBITDA.")?;
let plaintext = bob_group.process(&bob, &ciphertext)?;
assert_eq!(plaintext, b"Merger is at 4.2x EBITDA.");
// Every operation emits a jwp::ReceiptPayload; drop into your audit pipeline. One-line E2E over any channel
use joule_comm::encrypted::{EncryptedSender, decrypt_envelope};
// Wrap your channel router with an MLS layer — no changes to your
// downstream adapter code. Slack / Discord / SMS sees opaque
// `joule-comm-mls:v1:<base64>` envelopes; the recipient recovers
// plaintext via decrypt_envelope.
let mut sender = EncryptedSender::new(&mut router, &mut alice_group, &alice);
let receipts = sender.send(msg)?;
// returns both: receipts.mls (MLS encrypt receipt)
// receipts.channel (platform delivery receipt) 4 · Reference REST server
No Rust? Hit the server.
Ships as joule-comm-server
— a minimal axum binary exposing the SDK over REST. Deploy managed,
on-prem, or air-gapped. Every response carries a JWP
ReceiptPayload.
GET /api/v1/comm/health → surfaces ready + ciphersuite
POST /api/v1/comm/send → unified multi-channel send
POST /api/v1/comm/mls/identity → mint Ed25519 + key package
POST /api/v1/comm/mls/group → create MLS group
POST /api/v1/comm/mls/add → add member, return welcome bytes
POST /api/v1/comm/mls/join → join from welcome
POST /api/v1/comm/mls/send → encrypt, return ciphertext + receipt
POST /api/v1/comm/mls/process → decrypt incoming
Default listen address JOULE_COMM_ADDR=127.0.0.1:9216,
configurable via env. Shipping in the workspace today.
5 · Post-quantum roadmap
Today: MLS. Tomorrow: hybrid PQ.
Default ciphersuite is the RFC 9420 baseline:
MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519.
Forward-secure against classical adversaries; the post-quantum
ratchet story is landing 2026 H2.
Planned API addition (non-breaking):
joule_comm::mls::pq::Identity // Ed25519 + ML-DSA hybrid credential
joule_comm::mls::pq::GroupSession::pq_send // mixes classical + ML-KEM-768 ratchet
joule_comm::mls::pq::ratchet_step // periodic PQ key contribution Design based on Signal's SPQR (Sparse Post-Quantum Ratchet, 2025) and Apple's PQ3 (iMessage, 2024). Lands once the IETF MLS-PQ draft stabilises.
Integrate now
SDK is shipping under the joulesperbit
Rust workspace. Send us your use case — SMS OTP, contact-center,
federated messaging, sovereign remote — we'll come back with a
scoping document and a pricing schedule.