15 KiB
RFC-0910: FIRST-CLASS MESSAGING SYSTEM
The Submarine's Nervous System
Version: 0.1.0
Status: DRAFT
Layer: L0-L1 (Transport — Internal Process Communication)
Class: ARCHITECTURAL
Author: Markus Maiwald
Date: 2026-02-09
0. ABSTRACT
This document specifies the First-Class Messaging System for internal process communication within Libertaria nodes. It introduces a dual-plane architecture using Zenoh for the data plane (content-routed pub/sub) and NNG (nanomsg-next-generation) for the control plane (pattern-oriented messaging).
Key Principles:
- No-broker sovereignty: No Kafka, no RabbitMQ, no central daemon
- Kenya compliance: ~50-200KB footprint per library
- Layered encryption: LWF encryption (RFC-0000) overlays both transports
- Pattern + Content: Structural patterns (NNG) + namespace routing (Zenoh)
1. MOTIVATION
1.1 The Gap
Libertaria L0 (UTCP, LWF) handles inter-node communication. But intra-node communication—chatter between Membrane Agent, Feed processor, Sensor Oracle, and cognitive streams—lacks a first-class solution.
WebSockets are inappropriate (HTTP upgrade semantics where HTTP has no business). Raw TCP is too low-level. We need:
- Brokerless operation (sovereignty requirement)
- Pattern expressiveness (REQ/REP, PUB/SUB, PIPELINE)
- Content-based routing (subscribe to
sensor/berlin/pm25/**) - Kenya compliance (embedded-friendly footprint)
1.2 The Dual-Plane Insight
No single library satisfies all constraints. The solution is architectural:
| Plane | Library | Use Case | Pattern |
|---|---|---|---|
| Data | Zenoh | Sensor readings, Feed posts, economic signals | Content-routed pub/sub |
| Control | NNG | Agent negotiation, membrane stages, health checks | Pattern-oriented messaging |
Law: Zenoh is the data plane. NNG is the control plane. The submarine controls its own hull.
2. ZENOH: THE DATA PLANE
2.1 What is Zenoh?
Zero-overhead pub/sub with query semantics. Rust core, Eclipse Foundation lineage. Successor to DDS ecosystem.
2.2 Why Zenoh for Data?
- Key-expression routing:
sensor/berlin/pm25/**is first-class - Query + Pub/Sub unified:
get("sensor/berlin/pm25/latest")ANDsubscribe("sensor/berlin/pm25/*") - Peer-to-peer AND routed: Brokerless by default, routers for scale
- Wire efficiency: 4-8 bytes overhead per message (binary protocol)
- Storage alignment: Built-in persistence backends (RocksDB, memory)
- Zenoh-Pico: C library, ~50KB footprint (Kenya-compliant)
2.3 Zenoh Namespace Design
libertaria/
├── sensor/
│ └── {geohash}/
│ └── {metric_type}/
│ └── {reading} → sensor/9f4w/pm25/42.3
├── chapter/
│ └── {chapter_id}/
│ ├── feed/
│ │ └── {channel}/
│ │ └── {post_id} → chapter/berlin/feed/world/post-123
│ └── state/
│ └── {key} → chapter/berlin/state/governance
├── economy/
│ └── {token}/
│ └── {metric} → economy/scrap/velocity
└── agent/
└── {agent_id}/
└── {stream} → agent/janus-7/stream-2
2.4 Zenoh Integration Points
| Component | Subscription | Publication |
|---|---|---|
| Membrane Agent | sensor/+/pm25, chapter/+/feed/** |
Filtered feed items |
| Sensor Oracle | sensor/+/+ (all sensors) |
Normalized readings |
| Feed Relay | chapter/+/feed/channel/* |
Relayed posts |
| Economic Engine | economy/scrap/** |
Velocity updates |
| Archive Negotiator | chapter/+/feed/** (selective) |
ANP responses |
3. NNG: THE CONTROL PLANE
3.1 What is NNG?
Brokerless messaging library (nanomsg-next-generation). Pure C. Pattern-oriented.
3.2 Why NNG for Control?
- Pattern elegance: Declare intent (REQ/REP, PUB/SUB, PIPELINE), not plumbing
- Zig interop: Native C ABI,
@cImporttrivial - Transport agnostic:
ipc://,tcp://,inproc://(zero-copy same-process) - Zero broker: The pattern is the infrastructure
- Lightweight: ~200KB shared library (Kenya-compliant)
- SURVEY pattern: Perfect for "ask all sensors, collect within deadline"
3.3 NNG Patterns Used
PUB/SUB — Status Broadcasts
PUBLISHER (Health Monitor)
└── PUB socket → "ipc:///tmp/libertaria/health.pub"
SUBSCRIBERS
├── Membrane Agent (subscribe: "membrane.")
├── Feed Processor (subscribe: "feed.")
└── Chapter Governor (subscribe: "governor.")
REQ/REP — Agent Negotiation
REQUESTER (Membrane Agent)
└── REQ socket → "ipc:///tmp/libertaria/governor.rep"
└── "AUTHORIZE: post-123"
REPLIER (Chapter Governor)
└── REP socket ← "ipc:///tmp/libertaria/governor.rep"
└── "PERMIT: entropy=valid,qvl=trusted"
PIPELINE — Membrane Processing Stages
PUSH (Entropy Checker)
└── PUSH socket → "inproc:///membrane/stage1"
PULL → PUSH (Graph Checker)
└── PULL ← "inproc:///membrane/stage1"
└── PUSH → "inproc:///membrane/stage2"
PULL → PUSH (Periscope AI)
└── PULL ← "inproc:///membrane/stage2"
└── PUSH → "inproc:///membrane/stage3"
PULL (Accept/Reject)
└── PULL ← "inproc:///membrane/stage3"
SURVEY — Sensor Aggregation
SURVEYOR (Sensor Oracle)
└── SURVEY socket → "tcp://*:7890"
└── "QUERY: pm25_24h_max"
└── Deadline: 500ms
RESPONDENTS (Sensor Nodes)
└── RESPONDENT socket ← "tcp://sensor-oracle:7890"
└── Reply with local reading
4. DUAL-PLANE ARCHITECTURE
4.1 Node Interior Layout
┌─────────────────────────────────────────────────────────┐
│ LIBERTARIA NODE │
│ │
│ CONTROL PLANE (NNG) DATA PLANE (Zenoh) │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ REQ/REP │ │ sensor/berlin/pm25/* │ │
│ │ Agent negotiation│◄──────►│ chapter/+/feed/** │ │
│ └──────────────────┘ │ economy/scrap/** │ │
│ └──────────────────────┘ │
│ ┌──────────────────┐ │
│ │ PIPELINE │ ┌──────────────────┐ │
│ │ Membrane stages │ │ Membrane Agent │ │
│ │ (inproc://) │ │ (subscribes to │ │
│ └──────────────────┘ │ sensor/+/pm25) │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ SURVEY │ │ Feed Processor │ │
│ │ Health checks │ │ (subscribes to │ │
│ └──────────────────┘ │ chapter/+/feed) │ │
│ └──────────────────┘ │
│ │
│ ENCRYPTION: LWF (RFC-0000) overlays both planes │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Zenoh payload: XChaCha20-Poly1305 encrypted │ │
│ │ NNG payload: XChaCha20-Poly1305 encrypted │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
4.2 Transport Selection Decision Tree
Is the communication:
├── Content-defined? (sensor/berlin/pm25)
│ └── Use ZENOH (key-expression routing)
├── Pattern-defined? (REQ/REP negotiation)
│ └── Use NNG (pattern semantics)
├── High-frequency + small payload?
│ ├── >10k msgs/sec → ZENOH (lower overhead)
│ └── <10k msgs/sec → Either
├── Must survive intermittent connectivity?
│ └── ZENOH (designed for this)
└── Must guarantee delivery ordering?
└── NNG PIPELINE or REQ/REP
5. SECURITY: LWF ENCRYPTION OVERLAY
Neither Zenoh nor NNG provides native encryption that satisfies Libertaria's sovereignty requirements. Both use LWF encryption overlay (RFC-0000).
5.1 Zenoh + LWF
Zenoh payload structure:
┌─────────────────────────────────────────────────────┐
│ LWF Header (72 bytes) │
│ ├── Version, Frame Type, Session ID │
│ ├── Sequence, Timestamp │
│ └── Payload Length │
├─────────────────────────────────────────────────────┤
│ Encrypted Payload (XChaCha20-Poly1305) │
│ └── Contains: Zenoh binary message │
├─────────────────────────────────────────────────────┤
│ MAC (16 bytes) │
└─────────────────────────────────────────────────────┘
5.2 NNG + LWF
NNG message structure:
┌─────────────────────────────────────────────────────┐
│ NNG Protocol Header (minimal) │
├─────────────────────────────────────────────────────┤
│ LWF Encrypted Body │
│ └── XChaCha20-Poly1305(SoulKey-derived nonce) │
│ └── Contains: Application message │
└─────────────────────────────────────────────────────┘
Key Derivation: Per-session keys from X3DH handshake (RFC-0140), rotated per RFC-0010 epoch.
6. IMPLEMENTATION
6.1 Dependencies
// build.zig
const zenoh_pico = b.dependency("zenoh-pico", .{
.target = target,
.optimize = optimize,
});
const nng = b.dependency("nng", .{
.target = target,
.optimize = optimize,
});
exe.addModule("zenoh", zenoh_pico.module("zenoh"));
exe.linkLibrary(nng.artifact("nng"));
6.2 Zig API Example: Zenoh
const zenoh = @import("zenoh");
// Publisher
var pub = try zenoh.open(b.allocator, .{.mode = .peer});
var publisher = try pub.declare_publisher("sensor/berlin/pm25");
try publisher.put("42.3");
// Subscriber
var sub = try zenoh.open(b.allocator, .{.mode = .peer});
var subscriber = try sub.declare_subscriber("sensor/+/pm25", .{
.callback = onSensorReading,
});
fn onSensorReading(sample: zenoh.Sample) void {
const reading = sample.payload; // "42.3"
const key = sample.key; // "sensor/berlin/pm25"
std.log.info("{s}: {s}", .{key, reading});
}
6.3 Zig API Example: NNG
const nng = @cImport({
@cInclude("nng/nng.h");
});
// REQ socket
var req: nng.nng_socket = undefined;
_ = nng.nng_req0_open(&req);
_ = nng.nng_dial(req, "ipc:///tmp/libertaria/governor.rep");
const msg = "AUTHORIZE: post-123";
_ = nng.nng_send(req, msg.ptr, msg.len, 0);
var reply: ?*anyopaque = null;
var reply_len: usize = 0;
_ = nng.nng_recv(req, &reply, &reply_len, nng.NNG_FLAG_ALLOC);
std.log.info("Reply: {s}", .{@ptrCast([*]u8, reply)[0..reply_len]});
7. KENYA COMPLIANCE
| Library | Footprint | Kenya Status |
|---|---|---|
| Zenoh-Pico | ~50KB | ✅ Compliant |
| NNG | ~200KB | ✅ Compliant |
| Total | ~250KB | ✅ Compliant |
Both libraries:
- No mandatory broker (survives network partition)
- Low memory footprint (no JVM, no heavy runtime)
- C ABI (Zig interop without FFI complexity)
- Static linkable (single binary deployment)
8. MIGRATION PATH
Phase 1: Zenoh for Sensors (Week 1)
- Deploy Zenoh-Pico on sensor nodes
- Membrane Agent subscribes to
sensor/+/pm25 - Verify: 4-8 byte overhead per message
Phase 2: NNG for Membrane (Week 2)
- Implement PIPELINE for processing stages
- Replace ad-hoc channel communication
- Verify: Zero-copy
inproc://where possible
Phase 3: Unified Health (Week 3)
- NNG SURVEY for node health aggregation
- Zenoh pub for status broadcasts
- Unified dashboard
Phase 4: LWF Overlay (Week 4)
- Add XChaCha20-Poly1305 encryption to both transports
- Key rotation per RFC-0010 epochs
- Security audit
9. CONCLUSION
Zenoh is the data plane. NNG is the control plane.
This dual-plane architecture respects Libertaria's core constraints:
- Sovereignty: No broker, no external dependency
- Kenya: 50-200KB footprint
- Security: LWF encryption overlays both
- Expressiveness: Content routing (Zenoh) + Pattern semantics (NNG)
The submarine does not merely transport messages. It thinks through them.
APPENDIX: DEPENDENCIES
Zenoh-Pico
- URL: https://github.com/eclipse-zenoh/zenoh-pico
- License: EPL-2.0 OR Apache-2.0
- Zig binding: Direct C API via
@cImport
NNG (nanomsg-next-generation)
- URL: https://github.com/nanomsg/nng
- License: MIT
- Zig binding: Direct C API via
@cImport
End of RFC-0910 v0.1.0
The submarine's nervous system is waking up. 🜏