zBRETT
DE·EN
To the hardware →
Language: DE · EN
ARCHITECTURE & TRANSPORT · MVP SPEC

Usenet semantics
with SMS economics.

Core thesis: the mesh carries not the messages but the claim of existence. That turns the radio budget into a function of the event rate, not the data volume. MAUS/ZConnect semantics, IPFS data model, Reticulum transport. Guiding principle: robustness wins.

Concept completeMVP definitionAs of 2026-07-17
01

The problem

No system exists that carries structured, threaded, asynchronous discussion over radio. Existing approaches each cover one half.

ApproachCan doMissing
Meshtastictransportchannels without threading, without IDs, without history
Meshtastic Store & Forwardbufferingno board structure, no subscriptions
TC²-BBS / meshing-aroundBBS semanticsno differential sync, no duplicate detection
MeshCoreroom server with historyno subscription model

What's missing is exactly what MausTausch/ZConnect had solved from 1986 on: globally unique message IDs, reference chains (REF:) for thread reconstruction without full history, duplicate detection, and selective per-board subscriptions. Only then the cost function was the phone bill — today it's airtime.

02

Two message types, two economies

The incentive for short messages is audience, not price. Whoever posts a BEACON isn't read by mesh-only participants. Social sanction, no enforcement needed.

 INLINEBEACON
Content140 chars, in the packetteaser + CID, full text on the fat net
Size~76 B~108 B
Mesh cost, author1 packet1 packet
Mesh cost, reader01 packet + fetch
Readable without internet✓ yes✗ no
Reachall participantsfat-net class only
03

A board is a rule-space

Not just sorting — it declares the economy in force. Policy is a signed IPLD object; the node checks incoming messages against it. Violation = drop, no relay.

/DE/COMP/MESH/CHAT    accept: INLINE
/DE/SCI/PAPERS        accept: INLINE, BEACON | max_size: 512K
/DE/REGIO/BERLIN      accept: INLINE, BEACON | max_size: 64K | beacon_quota: 3/day/author
04

Architecture decisions (fixed)

#DecisionConsequence
A4Everyday network (not emergency)Retention, moderation, identity are mandatory. Hubs need 24/7 + solar.
A3Teaser flows into the content CIDBeacon tamper-proof. Forgery detectable only on fetch → relay reputation needed.
A2LXMF / Reticulum as transportCrypto + routing for free. Duty-cycle scheduling not included → build our own.
A1Duty cycle 1% (no LBT/AFA)~720 packets/day/node at SF11. Hub fan-out hard-capped at ~8–10 neighbours.
B1Single parentRobustness over expressiveness. Multi-parent rejected.
B2INLINE/BEACON at board levelEducates rather than flexibilises.
B3Merkle batch signaturesNo BLS/pairing crypto on the microcontroller.
B4Full CIDv1 (32 B)+20 B/beacon, but real IPFS interop with no mapping layer.
05

The stack

┌──────────────────────────────┐
│ NNTP frontend                │  ← any newsreader
├──────────────────────────────┤
│ Board logic, subs, retention │  ← new (brettd)
├──────────────────────────────┤
│ IPLD dag-cbor + CIDv1        │  ← IPFS data model
├──────────────────────────────┤
│ Minisketch sync              │  ← Bitcoin Erlay
├──────────────────────────────┤
│ Reticulum LXMF               │  ← transport, crypto
├──────────────────────────────┤
│ LoRa PHY                     │
└──────────────────────────────┘

IPFS: what we take

CIDv1 / content addressing and IPLD / dag-cbor — the reference tree is a Merkle DAG. Pinning as a subscription model formally defines the hub role: a hub is a pinning service with an airtime budget. CID references for long-form are a free internet bridge.

What we don't: Kademlia DHT (O(log n) round-trips of 3 s = minutes per lookup), libp2p/IPNS (handshake blows the budget). Bitswap only on the fat net. The break between radio and net sits exactly at the layer boundary where IPFS already has it.

06

Wire format

BEACON · dag-cbor · ~108 B → 1 packet at SF11
{
  b: h'a3f1',        //  2  board
  c: CID(32),        // 34  content address
  p: CID(32),        // 34  parent (single)
  a: h'9c2e4b81',    //  4  author prefix
  t: 29184301,       //  4  ts, minutes
  s: 3400,           //  2  size hint
  x: h'...'          // ~28 teaser, ~40 chars
}

The CID is the integrity guarantee

No signature in the beacon — author authenticity comes from the content block (room there for a 64 B Ed25519). INLINE (~76 B): the body is the block, no content CID needed — much cheaper than BEACON.

Compression

For 140-character strings a pre-trained dictionary is the entire compression — LZ77 finds nothing in 140 bytes. The character limit is thus a derived quantity: the boundary is in bytes after compression, the limit in characters before. inline_max follows from measurement M3, not the other way round.

A dictionary is a content-addressed IPLD object (not a central enum), carries a 4-bit index in the header for self-description, is a domain object rather than a language object, and the compressor never rejects — mixed language just compresses worse, that's all. Physics sanctions, not policy.

07

Sync: Minisketch instead of push

ZConnect/Fido used push with watermarks — which assumes ordered, reliable connections. LoRa has neither ordering nor reliability. Instead: set reconciliation over IBLT/Minisketch.

Node A                                    Node B
  |-- SYNC_REQ(board, sketch[128B], T-7d) ->|
  |                                          | decode(sketch_A XOR sketch_B)
  |<-- SYNC_RESP(want={CID5}, send={CID3,7}) |
  |-- BEACON(CID5) ------------------------->|
  |<-- BEACON(CID3), BEACON(CID7) -----------|

A sketch of 128 B reconstructs a difference of up to ~8 entries — regardless of whether the board holds 100 or 100,000 messages. A full weekly reconciliation at typical difference: ~7 packets ≈ 20 s airtime at SF11. One node keeps dozens of boards in sync within the daily budget.

08

The pager state machine

BEACON received (mesh)
   │
   ├─ board subscribed? ──no──→ DROP
   ├─ CID already local? ──yes─→ DROP (dupe)
   ▼
WANTLIST += CID
   │   [wait. minutes. hours. days.]
   ▼
fat net up? ──no──→ teaser stays visible
   ▼
BULK FETCH → IPFS gateway / hub
   ▼
verify CID → Ed25519 → into DAG → full text
Three network states
StateChannelExperience
Mesh onlyLoRasees that a discussion happens, plus a snippet
Mesh + gatewayLoRa + uplinkfull text on demand, with a wait
Fat netWi-Fi/LTEa normal forum

The CID is the same in all three states — no merge, no versioning, the DAG only grows. The beacon is a promise, the CID is the contract.

09

Topology

      [uplink gateway]  ←── internet / IPFS(LoRa, SF7, roof antenna)
      ┌─────┴─────┐
  [hub west]  [hub east]   ← S&F, 24/7, solar, max 8
    │    │      │    │
  [N] [N]     [N] [N]     ← endnodes, opportunistic

The hierarchy isn't convenience, it's the cost function. A flat mesh that floods every message everywhere burns the budget quadratically. Fido had zones/nets/nodes for the same reason — only then the currency was the long-distance call.

Consequence of A1 and the fan-out cap: a city network needs many hubs, not big ones.

10

Duty-cycle governor: LXMF vs. 1%

LXMF/Reticulum knows link establishment, retries, announces — but no airtime accounting. The RNode layer drops instead of delaying. Exactly wrong: a dropped beacon is lost, a delayed one arrives. LXMF is opportunistic, duty cycle is deterministic — incompatible scheduling philosophies.

Role separation
 EndnodeHub
Neighbours1–2up to 8
Send volumelowat the limit
Uptimesporadic24/7
SolutionLXMF vanillaDutyCycleInterface
The DutyCycleInterface — beneath RNS

At the layer boundary where airtime physically arises. Sees every packet, including Reticulum's own traffic:

Rolling-window airtime accounting (real ToA) Priority queue: BEACON > SYNC > announce > proof Delay instead of drop · announce thinning

Why not a governor above LXMF: Reticulum's own traffic (announces, path requests, handshakes) eats roughly 20–40% of the budget at 8 neighbours — a governor above it manages 60% and believes it's 100. The price of A2 is this governor — home-built, and the likeliest place for field-test surprises.

11

Governance

#QuestionDecision
C1Who may be a hub?Operator list + web of trust. Open won't do: 8 neighbour slots are a Sybil target.
C2RetentionPer board in the policy: retain: 180d / retain: pinned. The hub enforces.
C3Rate limitingToken bucket per author prefix, in the protocol. At 720 packets/day it's existential.
C4Who creates boards?A board exists once a hub pins its policy. Fido's zone coordinator without the title.
12

MVP scope & measurements

Software components
DutyCycleInterface — RNS interface, Python, hub only. Largest single item.
brettd — DAG store (SQLite), codec, Minisketch sync, wantlist+fetch, policy.
Minisketch wrapper — ctypes binding, ~200 lines.
NNTP frontend — read-only. The moment it feels like MAUS.
Measurements (block everything)

M1 — announce overhead

2× RNode, 24 h, 8 simulated neighbours. Without this number every budget is a guess. < 15% → a governor above LXMF is defensible; above → DutyCycleInterface has no alternative.

M2 — RNS timeout tolerance

How long may an interface delay before links break? Determines the maximum queue depth.

M3 — compression bake-off

Brotli vs. Zstd --train vs. token-Huffman. Metric: rate at the 5th percentile. Determines the compressor and inline_max. Provisional pick: Zstd.

13

Known risks

RiskAssessment
A2 + A1 is the sore spotLXMF knows nothing of duty cycle. The governor is home-built.
Fan-out 8Limits topology more than physics does. Many small hubs, not few big ones.
Asymmetric visibilityTwo classes in one discussion. Someone replies to a teaser without having read the full text. Culturally tricky.
Wantlist growth3 months without the fat net = thousands of CIDs. Needs prioritisation + expiry.
No real timeNeighbouring board in minutes, distant in hours. MAUS-1991 behaviour — duty cycle today instead of modem latency.