mirror of
https://gitea.jeffemmett.com/jeffemmett/rmesh-holonserve.git
synced 2026-06-25 16:45:22 +02:00
Bandwidth-disciplined HTTP-over-Reticulum publisher for rSpace holons
- Python 85.1%
- Shell 8.9%
- Rust 5.2%
- Dockerfile 0.8%
Public clients discover holons by connecting to the transport node's published 0.0.0.0:4262 (reachable on Netcup's public IP) — our Python rnsd relays announces to clients. Verified: a client on 159.195.32.209:4262 discovers hello/jeff/smoke. Reverts the multi-home-onto-rnsd-rs approach: investigated and rejected as fragile (every holonserve restart needs a transport-node flush, reproduced consistently) AND pointless (rnsd-rs/phantom don't relay announces to leaf clients, so nothing discovers via them). holonserve stays a single-backbone leaf; entrypoint simplified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| app | ||
| holonfetch | ||
| iroh-node | ||
| scripts | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| NOTES.md | ||
| README.md | ||
| requirements.txt | ||
| supervisord.conf | ||
holonserve
Bandwidth-disciplined HTTP-over-Reticulum publisher for rSpace holons.
Serves rSpace holon content at rweb://[hash]/ addresses with content-addressed chunks, delta sync, and hard size caps. Designed to survive 3.2 kbps LoRa — no React bundles, no fonts, text-first.
Threat Model
- Network: Reticulum mesh — adversarial relays, low bandwidth (LoRa: ~3.2 kbps), high latency
- Content integrity: ed25519 per-holon signing keys; manifests are signed; chunk hashes are blake2b-16
- Auth:
BRIDGE_API_KEYgates publish API; Reticulum identity gates mesh access - No encryption by default: Content-addressed = effectively public. Chunk encryption is Phase 2.
- DoS: Rate-limited announces (30s/holon, 5s global); link idle timeout 60s; max chunk request 16
Bandwidth Budget
| Asset type | Limit |
|---|---|
| Total holon (compressed) | 50 KB |
| Single file (compressed) | 32 KB |
| JavaScript | 8 KB |
| Fonts, PDFs, video | banned |
Publish API rejects at POST time with loud, human-readable reasons. CI fails. Holon author must slim.
Architecture
rmesh-reticulum (rnsd + LXMF bridge)
↕ shared_instance_port 37428
rmesh-holonserve
├── rns_worker — RNS destinations, link handling, IPC server
└── api (8001) — FastAPI publish endpoint, proxied by Traefik
↕ UDS IPC
Storage: /data/holonserve/{chunks,manifests,keys,holons.db}
Wire Format
Manifest (msgpack, ≤4 KB):
{"v":1, "holon_id":"alpha", "name":"Alpha Holon", "updated_at":1745280000,
"prev": <16B prev_manifest_hash or None>,
"chunks":[{"p":"/","h":<16B>,"m":"text/html","z":"br","s":1823}, ...],
"sig": <64B ed25519>}
Announce app_data (37 bytes, LoRa-frame-safe):
\x01 + holon_id_utf8[:16].ljust(16,\x00) + manifest_hash_16B + u32_be(manifest_size)
Link opcodes: HELLO (0x01), MANIFEST (0x02), CHUNK_REQ (0x03), CHUNK (0x04), DONE (0x05), ERR (0xFF)
Runbook
Deploy
cp .env.example .env
# Fill INFISICAL_CLIENT_ID + INFISICAL_CLIENT_SECRET
docker compose up -d
Publish a holon
./scripts/holonserve-publish.sh <holon_id> "<name>" ./dist-reticulum/
Announce to mesh
curl -H "X-Api-Key: $BRIDGE_API_KEY" -X POST http://localhost:8001/announce/<holon_id>
Fetch via CLI
holonfetch rweb://<manifest_hash_hex>/
holonfetch rweb://<manifest_hash_hex>/main.js -o /tmp/main.js
Build pipeline contract
Every rSpace holon CI must produce dist-reticulum/:
index.htmlwith inline critical CSS- No fonts, no analytics, no tracking, no heavy JS
- Optional
main.js ≤ 8 KBprogressive enhancement - Small SVGs inlined in HTML preferred
GC orphaned chunks
docker exec rmesh-holonserve python -c "from app.store import gc_chunks; print(gc_chunks(), 'chunks removed')"
Development
pip install -r requirements.txt
pytest tests/ # manifest + chunker + link_proto (no RNS needed)
python -m py_compile app/*.py holonfetch/*.py
docker compose config # validate compose
See NOTES.md for Infisical setup and RNS API caveats.