Election is coordination-free, so two replicas with divergent membership
views can each elect themselves the single writer for a key (split-brain),
and election has no way to make a deposed writer stop. Add the composable
fencing VALUE and SEAM that close this, with no I/O and no consensus folded in:
- Round uint64 monotone fencing epoch (the only value into storage)
- Lease{Key,Owner,Round} binds an elected owner to the round it writes at
- Fencer.Acquire seam round source plugs in behind it (linearizable store
today, Lux BFT round tomorrow) — never in this package
- StaticFencer(self) single-process fencer (round 1), mirrors Static
Invariant: round monotone per key, strictly increases on handoff, so a new
lease outranks every prior holder and the store (vfs/replica.FencedStore)
fences the old writer by refusing any lower round.
HRW (Rendezvous) single-writer election as its own coordination primitive
— no coordinator, lock service, Postgres, or Redis. Answers "who is the
single writer for key K" identically on every replica.
Extracted from hanzoai/vfs/replica/owner.go (HIP-0107), which was
storage-agnostic pure Go with no vfs-internal callers. Election (who
writes) and replication (how state ships) are orthogonal; this is the cut.
Generalizes orgID -> key (any ownership unit).
API: Member, Owner, IsOwner, Replicas + the Membership seam + Static.
Zero deps (stdlib crypto/sha256, encoding/binary, context).