macula_record (macula v8.4.0)
View SourcePKARR-compatible signed records (envelope + node_record + tombstone).
A record is a map carrying:
type(uint) — record type tag (0x01= node_record,0x0C= tombstone)key(32B) — owning Ed25519 pubkeyversion(16B) — UUIDv7created_at/expires_at(ms since epoch)payload(map) — type-specificsignature(64B) — Ed25519 signature; present aftersign/2
On the wire records are CBOR maps with single-letter keys (t, k, v, c, x, p, s) per Part 6 §9. Signatures are Ed25519 over "macula-v2-record\0" ++ canonical_cbor(unsigned).
Summary
Functions
Generic record builder. Used internally by every typed constructor and exposed publicly for domain-defined record types in the 0x20-0xFF tag range. Returns an UNSIGNED record map; pair with sign/2.
Build an unsigned host_delegation. Pair with sign_host_delegation/2.
Build a host-signed redirect from a daemon address to its hosting station. Pair with sign/2 (signed by the host's key, NOT the daemon's). Caller is responsible for embedding a delegation that's already been daemon-signed.
The DHT storage key for a procedure by its URI, without a record in hand: SHA-256(procedure_uri), identical to storage_key/1 for a procedure_advertisement (Part 3 §3.3). Consumers use this to find_records/2 before holding any record.
Read a procedure_advertisement record's fields as a typed map, hiding the payload's wire keying from consumers. Pairs with the procedure_advertisement/3,4 constructors.
Read a station_endpoint record's fields as a typed map, hiding the payload keying (robust to canonical vs wire-decoded, like read_procedure_advertisement/1). host_advertised is a possibly empty list of host binaries.
Rebuild a record with a fresh UUIDv7 version and a new created_at / expires_at pair (preserving the original TTL), then re-sign with Identity. Used by the owner's tRepublish loop (Part 3 §11) to keep a record alive across churn without changing its type, key, or payload.
Sign the delegation with the daemon's keypair (the daemon authorises the host). Adds daemon_sig.
The DHT storage key for a station's endpoint by its pubkey, without a record in hand: identical to storage_key/1 for a station_endpoint. Consumers use this to find_record/2 a serving_station's dialable host:port.
Verify a signed delegation. Returns the delegation map on success.
Types
-type address_pubkey_map_opts() :: #{ttl_ms => pos_integer()}.
-type content_announcement_opts() :: #{name => binary(), size => non_neg_integer(), chunk_count => non_neg_integer(), ttl_ms => pos_integer()}.
-type foundation_parameter_opts() :: #{valid_from => pos_integer(), valid_until => pos_integer(), prior_version => <<_:128>> | undefined, ttl_ms => pos_integer()}.
-type foundation_realm_trust_list_opts() :: #{realms_revoked => [macula_identity:pubkey()], valid_until => pos_integer(), ttl_ms => pos_integer()}.
-type foundation_seed() :: #{node_id := macula_identity:pubkey(), addresses := [map()], tier := 3 | 4}.
-type foundation_seed_list_opts() :: #{valid_from => pos_integer(), valid_until => pos_integer(), ttl_ms => pos_integer()}.
-type foundation_t3_attestation_opts() :: #{valid_until => pos_integer(), notes => binary(), ttl_ms => pos_integer()}.
-type host_delegation() :: #{daemon_pubkey := <<_:256>>, host_pubkey := <<_:256>>, realm_pubkey := <<_:256>>, not_before_ms := pos_integer(), not_after_ms := pos_integer(), daemon_sig => <<_:512>>}.
-type hosted_address_map_opts() :: #{ttl_ms => pos_integer()}.
-type node_record_opts() :: #{station_id => macula_identity:pubkey(), caps_hint => binary(), display_name => binary(), ttl_ms => pos_integer(), hostname => binary(), endpoint => binary(), city => binary(), country => binary(), lat => float() | integer(), lng => float() | integer(), kind => binary(), peers => [macula_identity:pubkey()]}.
-type procedure_advertisement_opts() :: #{session_token_hint => binary(), rate_limit_qps => non_neg_integer(), max_concurrency => non_neg_integer(), ttl_ms => pos_integer()}.
-type realm_directory_opts() :: #{policy_url => binary(), ttl_ms => pos_integer()}.
-type realm_member_endorsement_opts() :: #{valid_from => pos_integer(), valid_until => pos_integer(), ttl_ms => pos_integer()}.
-type realm_station_entry() :: #{station_id := macula_identity:pubkey(), roles := [binary()]}.
-type realm_stations_opts() :: #{ttl_ms => pos_integer()}.
-type record() :: #{type := type_tag(), key := <<_:256>>, version := version(), created_at := pos_integer(), expires_at := pos_integer(), payload := map(), signature => <<_:512>>}.
-type station_endpoint_opts() :: #{host_advertised => [binary()], alpn => binary(), ttl_ms => pos_integer()}.
-type tombstone_opts() :: #{detail => binary(), ttl_ms => pos_integer()}.
-type type_tag() :: 1..255.
-type version() :: <<_:128>>.
Functions
-spec address_pubkey_map(macula_identity:pubkey(), Addr :: <<_:128>>) -> record().
-spec address_pubkey_map(macula_identity:pubkey(), Addr :: <<_:128>>, address_pubkey_map_opts()) -> record().
-spec content_announcement(macula_identity:pubkey(), binary(), binary()) -> record().
-spec content_announcement(macula_identity:pubkey(), binary(), binary(), content_announcement_opts()) -> record().
Generic record builder. Used internally by every typed constructor and exposed publicly for domain-defined record types in the 0x20-0xFF tag range. Returns an UNSIGNED record map; pair with sign/2.
The key field is always the signer's 32-byte Ed25519 public key (verify/1 looks it up there). For facts where one signer publishes about many subjects (e.g., a realm admin signing many license records), pass a subject_id opt — storage_key/1 derives a per-subject 32-byte slot via BLAKE3(<<type, key, subject_id>>). Without subject_id the storage key is key verbatim (one DHT slot per signer).
Domain code names its own payload fields. Single-letter wire keys (Part 6 §9) are an envelope-level concern; payloads use whatever naming makes sense in the domain.
-spec foundation_parameter(macula_identity:pubkey(), binary(), foundation_parameter_value()) -> record().
-spec foundation_parameter(macula_identity:pubkey(), binary(), foundation_parameter_value(), foundation_parameter_opts()) -> record().
-spec foundation_realm_trust_list(macula_identity:pubkey(), [macula_identity:pubkey()]) -> record().
-spec foundation_realm_trust_list(macula_identity:pubkey(), [macula_identity:pubkey()], foundation_realm_trust_list_opts()) -> record().
-spec foundation_seed_list(macula_identity:pubkey(), [foundation_seed()]) -> record().
-spec foundation_seed_list(macula_identity:pubkey(), [foundation_seed()], foundation_seed_list_opts()) -> record().
-spec foundation_t3_attestation(macula_identity:pubkey(), macula_identity:pubkey(), pos_integer()) -> record().
-spec foundation_t3_attestation(macula_identity:pubkey(), macula_identity:pubkey(), pos_integer(), foundation_t3_attestation_opts()) -> record().
-spec host_delegation(DaemonPk :: <<_:256>>, HostPk :: <<_:256>>, Realm :: <<_:256>>, NotBeforeMs :: pos_integer(), NotAfterMs :: pos_integer()) -> host_delegation().
Build an unsigned host_delegation. Pair with sign_host_delegation/2.
-spec host_delegation(<<_:256>>, <<_:256>>, <<_:256>>, pos_integer(), pos_integer(), map()) -> host_delegation().
-spec hosted_address_map(HostPk :: <<_:256>>, DaemonAddr :: <<_:128>>, Delegation :: host_delegation()) -> record().
Build a host-signed redirect from a daemon address to its hosting station. Pair with sign/2 (signed by the host's key, NOT the daemon's). Caller is responsible for embedding a delegation that's already been daemon-signed.
-spec hosted_address_map(<<_:256>>, <<_:128>>, host_delegation(), hosted_address_map_opts()) -> record().
-spec node_record(macula_identity:pubkey(), [macula_identity:pubkey()], non_neg_integer()) -> record().
-spec node_record(macula_identity:pubkey(), [macula_identity:pubkey()], non_neg_integer(), node_record_opts()) -> record().
-spec procedure_advertisement(macula_identity:pubkey(), binary(), macula_identity:pubkey()) -> record().
-spec procedure_advertisement(macula_identity:pubkey(), binary(), macula_identity:pubkey(), procedure_advertisement_opts()) -> record().
-spec procedure_key(binary()) -> <<_:256>>.
The DHT storage key for a procedure by its URI, without a record in hand: SHA-256(procedure_uri), identical to storage_key/1 for a procedure_advertisement (Part 3 §3.3). Consumers use this to find_records/2 before holding any record.
-spec read_procedure_advertisement(record()) -> #{procedure_uri := binary(), advertiser_node := macula_identity:pubkey(), serving_station := macula_identity:pubkey()}.
Read a procedure_advertisement record's fields as a typed map, hiding the payload's wire keying from consumers. Pairs with the procedure_advertisement/3,4 constructors.
Robust to both shapes a record can arrive in: the canonical form ({text, <<"k">>} keys, {text, V} text values, as built locally) AND the wire-decoded form (bare <<"k">> keys, bare values, as a record returned over an RPC like find_records/2). Consumers get the same map either way, so they never touch the CBOR keying.
Read a station_endpoint record's fields as a typed map, hiding the payload keying (robust to canonical vs wire-decoded, like read_procedure_advertisement/1). host_advertised is a possibly empty list of host binaries.
-spec realm_directory(macula_identity:pubkey(), binary(), macula_identity:pubkey()) -> record().
-spec realm_directory(macula_identity:pubkey(), binary(), macula_identity:pubkey(), realm_directory_opts()) -> record().
-spec realm_member_endorsement(macula_identity:pubkey(), #{realm := macula_identity:pubkey(), member_node := macula_identity:pubkey(), roles := [binary()]}) -> record().
-spec realm_member_endorsement(macula_identity:pubkey(), #{realm := macula_identity:pubkey(), member_node := macula_identity:pubkey(), roles := [binary()]}, realm_member_endorsement_opts()) -> record().
-spec realm_stations(macula_identity:pubkey(), [realm_station_entry()]) -> record().
-spec realm_stations(macula_identity:pubkey(), [realm_station_entry()], realm_stations_opts()) -> record().
-spec refresh(record(), macula_identity:key_pair() | macula_identity:privkey()) -> record().
Rebuild a record with a fresh UUIDv7 version and a new created_at / expires_at pair (preserving the original TTL), then re-sign with Identity. Used by the owner's tRepublish loop (Part 3 §11) to keep a record alive across churn without changing its type, key, or payload.
The new signature replaces any prior signature; callers can safely pass an already-signed record — the prior signature is stripped before re-signing.
-spec sign(record(), macula_identity:key_pair() | macula_identity:privkey()) -> record().
-spec sign_host_delegation(host_delegation(), macula_identity:key_pair() | macula_identity:privkey()) -> host_delegation().
Sign the delegation with the daemon's keypair (the daemon authorises the host). Adds daemon_sig.
-spec station_endpoint(macula_identity:pubkey(), QuicPort :: 1..65535) -> record().
-spec station_endpoint(macula_identity:pubkey(), QuicPort :: 1..65535, station_endpoint_opts()) -> record().
-spec station_endpoint_key(macula_identity:pubkey()) -> <<_:256>>.
The DHT storage key for a station's endpoint by its pubkey, without a record in hand: identical to storage_key/1 for a station_endpoint. Consumers use this to find_record/2 a serving_station's dialable host:port.
-spec storage_key(record()) -> <<_:256>>.
-spec tombstone(macula_identity:pubkey(), type_tag(), atom()) -> record().
-spec tombstone(macula_identity:pubkey(), type_tag(), atom(), tombstone_opts()) -> record().
-spec verify_host_delegation(host_delegation()) -> {ok, host_delegation()} | {error, term()}.
Verify a signed delegation. Returns the delegation map on success.