ClusterClient
A Raft learner-client that proposes commands through the cluster leader and exposes the committed log stream for state-machine application.
Obtain an instance via clusterClientWithNode (tests / caller-managed transport) or via the CoroutineScope.clusterClient extension (production relay-room usage, available in S3b once the Seam-reconnect transport adapter is wired).
Exactly-once proposals
propose (no-arg overload) delegates to RaftNode.propose which auto-mints and persists a monotonic requestId internally — a retry after failover with the same id coalesces to the original committed entry via us.tractat.kuilt.raft.ClientSessionTable.shouldApply.
propose with an explicit requestId is the public cross-crash exactly-once overload: callers that persist a requestId and replay it after a crash get at-most-once application of the command.
Failover model (S3a API contract; S3b wires the production path)
On transport tear the underlying ServerClusterReconnect advances to the next endpoint. When it presents the previous us.tractat.kuilt.session.partition.ResumeToken to the new server, the response is us.tractat.kuilt.session.partition.ResumeResult.WindowClosed (proven by #532): each server's reconnect window registry is in-memory and per-host-room, so a cross-server resume always degrades to fresh-join. ClusterClient treats WindowClosed as a fall-back-to-fresh-join signal, not an error.
See also
for the test / caller-managed-transport construction path.