auki-domain
This page mirrors crates/auki-domain/README.md in the auki-sdk repo (branch develop).
The repository is the source of truth.
The SDK's network-presence layer. An app that wants its peer and session visible in a cluster calls Domain::join(&peer, &session, DomainConfig) — this crate composes the two auki-session halves, bootstraps a ClusterManager, and serves the session's resource catalog to remote peers. Post-#282 the dependency points from auki-domain to auki-session, not the other way around.
Status: Shipped. App-facing via Domain; ClusterManager is the engine underneath.
Public surface
Domain — the app entry point
Domain::join(&Peer, &Session, DomainConfig)(async) — bootstraps the cluster perconfig.target, wraps the session's logs + peer's registries in a live catalog bridge (SessionHandle), and stamps the session identity intoDaemonInfo:- Identity guard (#284): before bootstrap or Discovery I/O, rejects unless the supplied
Peer, originatingSession, configuredPeerIdentity, and pre-built swarm local peer id are identical. - Clock stamping (#284):
daemon_info.session_id/session_clock_id/session_clock_hashare overwritten from the session's auto-minted monotonic clock; apps pass placeholders.
- Identity guard (#284): before bootstrap or Discovery I/O, rejects unless the supplied
Domain::catalog()→Vec<ResourceEntry>— the rows currently served over/auki/resources/0.2.0.DomainBuilder::new(&Peer, &Session, DomainConfig).message_channel(row, capacity).join()— composes receiver-owned live message channels before join. It validates that each row owner is the joiningPeer, that the clockRegistryRefexactly matches a clock registered in the suppliedSession(peer/id/hash), and rejects duplicate owner/resource-id pairs before binding the v0.3 catalog row, bounded receiver, andNetworkRuntimeregistration together.Domain::take_message_channel_receiver(resource_id)→MessageChannelReceiver— hands the application the declared bounded async receiver. EachMessageEventcarries the exact channel Resource, authenticated senderPeerId, opaque type string,timestamp_ns, and opaque payload. The receiver owns registration lifetime: dropping it removes the v0.3 row and closes channel endpoints; Domain leave/drop also closes a retained receiver.Domain::fetch_resources_catalog_v3[_with](https://github.com/aukilabs/auki-sdk/blob/develop/crates/auki-domain/peer, ...)— explicitly fetches/auki/resources/0.3.0; an unsupported peer returnsFetchResourcesCatalogV3Error::UnsupportedProtocoland there is no silent fallback to v0.2.Domain::fetch_resources_catalog(peer)remains the unchanged v0.2 fetch.Domain::fetch_map_catalog(peer)— fetches/auki/resources/0.4.0Map Log rows.Domain::open_map_stream(peer, row, read_from)validates the authenticated writer and accept-time Map/clock identity before exposing typed replay plus liveMapUpdates.Domain::open_message_channel(peer, &row)— verifies the discovered row owner equals the authenticated serving peer and returns a persistentMessageChannelSender.Domain::send_message(...)is the open/send-once convenience.Domain::cluster_manager()→&ClusterManager— escape hatch to the engine (membership, Manager state, domain clock estimates, participant info, stream opens).Domain::leave()(async) — clean shutdown of the cluster presence.catalog_of(&Peer, &Session)→Vec<ResourceEntry>— pure helper, no network; builds exactly the rowsDomainwould serve. Useful for tests and dry runs.
DomainConfig fields: target: ClusterTarget, local_identity: PeerIdentity, local_multiaddrs: Vec<Multiaddr>, discovery_url: String, swarm: Swarm<Behaviour>, stream_provider: StreamProvider, daemon_info: DaemonInfo.
Typed messaging is live and ephemeral. Send success is only a transport ACK
after the receiver runtime queues the event; it is not application acceptance.
If queueing succeeds but the ACK is lost, send returns an error even though the
event may already have been delivered. Callers must treat that result as
indeterminate and must not automatically retry.
There is no history, persistence, retry, replay, queue across disconnect,
materialization, or SDK interpretation of type/payload/timestamp. The channel
Resource carries an existing clock RegistryRef; each message carries only
timestamp_ns. Applications use existing clock declarations and time
transforms and own freshness, scheduling, and action policy.
Any current Noise-authenticated cluster member may send in this milestone.
NetworkRuntime membership is the coarse trust boundary; there is no generic
channel-level ACL. Unknown and removed peers cannot deliver payloads to the
application receiver.
ClusterManager — the engine
ClusterManager handles Discovery + cluster bootstrap: list / create / join / bootstrap (policy-driven via ClusterTarget), membership, Manager election + rotation, Discovery liveness checks, relay hint preservation, participant info, v0.2/v0.3/v0.4 resource catalog serving/fetching, hash-pinned registry-entry fetch (including Maps), typed stream and message-channel opens, domain clock estimates, and clean shutdown. SessionHandle is defined in auki-network to avoid a dependency cycle.
Manager arbitration
Discovery's cluster row is the tiebreak authority for the Manager role: a peer
holds the role only while the row names it. Election only nominates — a
successful rotate_manager (or row re-create after a sweep) commits. A
follower that loses Manager heartbeats consults Discovery before electing:
defer + rejoin while the row still names the lost Manager, follow +
rejoin when the row names someone else, elect only when the row was
swept. A Manager whose liveness response names another peer steps down and
rejoins it. Re-joining as a current member is idempotent (multiaddrs refresh;
join_ts_ns — and therefore election order — unchanged). A follower watches
its current Manager even when it is not in the local membership document, so
displaced or evicted peers keep retrying instead of stranding. Discovery
unreachable means no election can commit; the cluster runs headless on the
data plane until Discovery returns. Dropping a ClusterManager without
shutdown() aborts its background tasks, so a dead handle cannot keep the
row fresh.
Peers can join the cluster before their resource catalog is ready. The resources handler answers each inbound /auki/resources/0.2.0 request with a fresh snapshot from the registered ResourceCatalogProvider, or from SessionHandle::catalog() when no provider is installed. Producers should only return resources that can currently accept stream opens; unavailable resources are omitted until they become requestable again.
Also exported
ClusterManager,ClusterTarget,DaemonInfo,ResourceCatalogProvider,elect_successor(...),LIVENESS_CHECK_INTERVAL,DiagnosticMessage/InboundDiagnosticMessage,DiscoveryClusterEntry- Error types:
AdmitError,BootstrapError,CreateClusterError,JoinClusterError,DiscoveryClientError,FetchParticipantInfoError,FetchRegistryEntryError,FetchResourcesCatalogError,FetchResourcesCatalogV3Error,FetchMapCatalogError,DomainBuilderError,DomainOpenMapStreamError,DomainOpenMessageChannelError,DomainSendMessageError,DomainClockEstimateUnavailable,DomainTimeNowError ClusterMembership,ClusterMemberStreamManifestBuilder(+BuildStreamManifestError)- Re-exports:
SessionHandle,RegistryKind, v0.2ResourceEntry/ResourcesRequest/ResourcesResponse, v0.3ResourceEntryV3/ResourceVariantV3/ResourcesRequestV3/ResourcesResponseV3, v0.4MapLogResource/ResourcesResponseV4,MapUpdate,MessageChannelResource/MessageChannelSender(fromauki-network);ClockTransformEstimate/DomainClockEstimate(fromauki-time);SensorRegistryEntry/ClockRegistryEntry/FrameRegistryEntry/MapRegistryEntry(fromauki-registry)
Depends on
auki-session—Peer+Session, composed byDomain. This is the #282 inversion: the session layer knows nothing about domains.auki-network— libp2p, peer protocols, Discovery client, and theSessionHandletrait.auki-identity— Wallet → PeerId derivation.auki-hash,auki-jcs(optional) — canonical membership / cluster docs.auki-registry(optional) — hash-pinned registry-entry fetch.auki-time(optional) — clock-stamped membership / heartbeat, clock-sync estimates.