macula_topic (macula v3.13.0)

View Source

Mesh topic construction and validation.

Every mesh topic follows a strict 5-segment structure:

{realm}/{publisher}/{publisher}/{domain}/{name}_v{N}

The two publisher slots carry different values depending on the topic's ownership tier. Three tiers exist:

realm: {realm}/_realm/_realm/{domain}/{name}_v{N} org: {realm}/{org}/_org/{domain}/{name}_v{N} app: {realm}/{org}/{app}/{domain}/{name}_v{N}

Tier answers: who owns the topic's schema and authority?

realm — realm authority (membership, identity, ban) org — org-spanning concept (licensing, billing) app — app-internal (game state, RPCs, app events)

Use realm_fact / org_fact / app_fact for pub/sub topics (past tense names — something happened).

Use realm_hope / org_hope / app_hope for RPC procedure names (present tense names — we want something to happen).

System topics (with leading underscore — _mesh.*, _dist.*, _dht.*) are infrastructure-owned, dot-separated, and exempt from this 5-segment structure.

Full guide: docs/guides/TOPIC_NAMING_GUIDE.md

Summary

Functions

Build an app-tier fact topic. A specific app owns the schema. All slots carry real values.

Build an app-tier hope procedure name.

Build a topic from explicit segments. Validates each segment and the publisher-slot tier combination. Prefer the tier-specific builders (realm_fact, org_fact, app_fact).

Check if a topic is a system topic. System topics use the leading-underscore convention (e.g. _mesh.node.up, _dist.tunnel.X, _dht.list_gateways). They are infrastructure-owned, dot-separated, and exempt from the canonical 5-segment structure. Out of scope for this validator — passed through as-is.

Build an org-tier fact topic. An org owns the schema across multiple of its apps. The app slot carries the _org sentinel.

Build an org-tier hope procedure name.

Parse a topic into its constituent parts and tier. Returns an error tuple for any non-canonical topic. System topics (leading underscore prefix) are not canonical and will return an error from parse/1; use validate/1 to accept system topics as well.

Build a realm-tier fact (pub/sub) topic. Realm authority owns the schema. Publisher and subscriber slots carry the _realm sentinel.

Build a realm-tier hope (RPC) procedure name.

Validate a topic string. Accepts canonical 5-segment topics AND system topics (leading underscore prefix infrastructure events).

Types

app/0

-type app() :: binary().

domain/0

-type domain() :: binary().

name/0

-type name() :: binary().

org/0

-type org() :: binary().

realm/0

-type realm() :: binary().

tier/0

-type tier() :: realm | org | app.

topic/0

-type topic() :: binary().

version/0

-type version() :: pos_integer().

Functions

app_fact(Realm, Org, App, Domain, Name, Version)

-spec app_fact(realm(), org(), app(), domain(), name(), version()) -> topic().

Build an app-tier fact topic. A specific app owns the schema. All slots carry real values.

app_hope(Realm, Org, App, Domain, Name, Version)

-spec app_hope(realm(), org(), app(), domain(), name(), version()) -> topic().

Build an app-tier hope procedure name.

build(Realm, Org, App, Domain, Name, Version)

-spec build(realm(), org() | binary(), app() | binary(), domain(), name(), version()) -> topic().

Build a topic from explicit segments. Validates each segment and the publisher-slot tier combination. Prefer the tier-specific builders (realm_fact, org_fact, app_fact).

is_system_topic(_)

-spec is_system_topic(binary()) -> boolean().

Check if a topic is a system topic. System topics use the leading-underscore convention (e.g. _mesh.node.up, _dist.tunnel.X, _dht.list_gateways). They are infrastructure-owned, dot-separated, and exempt from the canonical 5-segment structure. Out of scope for this validator — passed through as-is.

org_fact(Realm, Org, Domain, Name, Version)

-spec org_fact(realm(), org(), domain(), name(), version()) -> topic().

Build an org-tier fact topic. An org owns the schema across multiple of its apps. The app slot carries the _org sentinel.

org_hope(Realm, Org, Domain, Name, Version)

-spec org_hope(realm(), org(), domain(), name(), version()) -> topic().

Build an org-tier hope procedure name.

parse(Topic)

-spec parse(topic()) -> {ok, map()} | {error, term()}.

Parse a topic into its constituent parts and tier. Returns an error tuple for any non-canonical topic. System topics (leading underscore prefix) are not canonical and will return an error from parse/1; use validate/1 to accept system topics as well.

realm_fact(Realm, Domain, Name, Version)

-spec realm_fact(realm(), domain(), name(), version()) -> topic().

Build a realm-tier fact (pub/sub) topic. Realm authority owns the schema. Publisher and subscriber slots carry the _realm sentinel.

realm_hope(Realm, Domain, Name, Version)

-spec realm_hope(realm(), domain(), name(), version()) -> topic().

Build a realm-tier hope (RPC) procedure name.

validate(Topic)

-spec validate(topic()) -> ok | {error, term()}.

Validate a topic string. Accepts canonical 5-segment topics AND system topics (leading underscore prefix infrastructure events).