Macula SDK

View Source

License Erlang/OTP Hex.pm Buy Me A Coffee

Macula

Erlang/OTP client SDK for the Macula HTTP/3 mesh


Latest — 9.1.1: every guide and this README checked line-by-line against real source — fabricated modules, a nonexistent legacy RPC API, a dead dependency pin, and a dozen other doc bugs found and fixed. No behavior change. See CHANGELOG.md for the full list. 9.1.0 added OTP 29 readiness (bare catch rewritten to try/catch/end; macula_record's record() type renamed m_record()) and the Records Guide. 9.0.0 was breaking: LAN clustering and distribution-over-mesh split into independent concerns — macula_cluster_system/ vs. macula_dist_system/. macula_dist_relay is renamed macula_dist_pool (the facade, join_mesh/1 / join_dist_relay/1, is unaffected); the auto_cluster sys.config option is removed (start clustering explicitly via macula_cluster:start_cluster/1). See CHANGELOG.md for the full history.

What is Macula?

Macula SDK Component and Feature Model

Macula is an Erlang/OTP client SDK for building applications on a mesh of stations — realm-agnostic relays that route over QUIC (HTTP/3) and form a Kademlia DHT. Your service or daemon connects outbound to one or more stations: no open ports, NAT-friendly, no VPN. It provides:

  • RPC (request/response) — discover a provider in the DHT, then dial its serving station directly (one hop), with optional realm-CA trust verification.
  • Pub/Sub — topic-based event fan-out across stations, with per-publisher ordered delivery.
  • Content — content-addressed sharing and live streaming (MCID).
  • DHT records — signed, TTL'd records (advertisements, endpoints, more).
  • Erlang distribution over meshnet_adm:ping across firewalls, no VPN.
  • Identity — Ed25519 keypairs, UCAN tokens, DID documents (NIF-accelerated).
  • MRI — typed, hierarchical resource identifiers.
  • Zero-config LAN clustering — UDP-multicast gossip.

The station (routing, DHT, SWIM, peering) is a separate repo, macula-station; this package is the client you build against.


Quick Start

Add to rebar.config:

{deps, [{macula, "~> 9.1"}]}.

Or in Elixir mix.exs:

defp deps do
  [{:macula, "~> 9.1"}]
end

SDK Connect Flow

application:ensure_all_started(macula),

%% Connect a pool to one or more stations (seed URLs). The pool owns one
%% QUIC link per seed, reconnecting and replaying subscriptions as needed.
{ok, Pool} = macula:connect([<<"quic://boot.macula.io:443">>], #{}),

%% A realm is a 32-byte tag derived from a name; it scopes every call.
Realm = macula_realm:id(<<"io.example.myapp">>),

%% Subscribe (delivers {macula_event, Ref, Topic, Payload, Meta} to a pid),
{ok, Ref} = macula:subscribe(Pool, Realm, <<"sensors.temperature">>, self()),

%% or subscribe with a callback fun(Topic, Payload, Meta):
{ok, Ref2} = macula:subscribe_callback(
    Pool, Realm, <<"sensors.temperature">>,
    fun(_Topic, Payload, _Meta) -> io:format("~p~n", [Payload]) end),

%% Publish. Entity IDs go in the PAYLOAD, never in the topic.
ok = macula:publish(Pool, Realm, <<"sensors.temperature">>,
                    #{sensor => <<"kitchen">>, value => 23.5}),

%% Advertise an RPC procedure (open to any identified caller here),
ok = macula:advertise(Pool, Realm, <<"math.add">>,
                      fun(#{<<"a">> := A, <<"b">> := B}) -> {ok, A + B} end,
                      #{}),

%% Call it — the SDK resolves the provider and dials its station directly.
{ok, 5} = macula:call(Pool, Realm, <<"math.add">>,
                      #{<<"a">> => 2, <<"b">> => 3}, 5_000).

Identity and Crypto (NIF-accelerated)

Identity and Crypto Stack

Rust NIFs with pure-Erlang fallbacks:

%% Ed25519 keypair (a #{public := _, private := _} map)
KP  = macula_identity:generate(),
Sig = macula_identity:sign(<<"hello">>, KP),
true = macula_identity:verify(<<"hello">>, Sig, macula_identity:public(KP)),

%% BLAKE3 hashing
Hash = macula_blake3_nif:hash(Data),

%% UCAN capability tokens + DID documents
{ok, Token}   = macula_ucan_nif:create(Issuer, Audience, Caps, PrivKey),
{ok, Payload} = macula_ucan_nif:verify(Token, PubKey).

Documentation

GuideDescription
ConnectingPools, seeds, TLS policy, reconnection
PubSub GuideFan-out + per-publisher delivery ordering
Topic NamingEvent-type topics, IDs in payloads
RPC GuideDirect-dial request/response
Content GuideContent-addressed blobs (MCID)
Records GuideSigned, TTL'd facts in the DHT — your own record types
Streaming GuideStreaming RPC (server / client / bidi)
Distribution Over MeshErlang dist through the mesh
ClusteringLAN gossip clustering
AuthorizationDID / UCAN / cert-chain trust
MRI GuideResource identifiers
DevelopmentBuilding and testing
GlossaryTerminology

The station server lives in macula-station.


ProjectDescription
macula-stationThe station: DHT, SWIM, routing, peering
macula-realmManaged-realm identity + certificate authority
macula-mri-khepriDistributed MRI persistence (Khepri/Raft)
macula-ecosystemDocumentation hub

License

Apache 2.0 — see LICENSE.


Built with the BEAM