changeMembership
Requests a cluster membership change to target, suspending until the change commits as C_new, then returning target.
Only the leader may call this. On non-leaders the default implementation throws NotLeaderException immediately, so FakeRaftNode in :kuilt-raft-test requires no change — it inherits this default.
Two change classes
If target.voters equals the current voter set (a learner-set-only change), a single Simple(target) config entry is appended — quorum is unchanged. If the voter set differs (a voter-set change), the transition goes through joint consensus: a Joint(C_old, C_new) entry is appended first (both old and new majorities are required for commit and election during this phase), and once it commits a final Simple(C_new) entry is appended. The call suspends until that Simple(C_new) commits. If this leader is not a voter in C_new, it steps down once C_new is durable.
Failure modes
NotLeaderException — this node is not the leader.
MembershipChangeInProgressException — a config entry is already uncommitted; only one change may be in flight at a time.
IllegalArgumentException — target.voters is empty.
LeadershipLostException — leadership was lost mid-transition; the change may or may not have committed on some nodes.