docs(redundancy): SelfFormAfter closes the seed-node bootstrap gap

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-22 06:10:11 -04:00
parent b8ac7e35e6
commit b853185cfd
7 changed files with 666 additions and 5 deletions
@@ -85,6 +85,12 @@ Their failover drill has a mode that exists *"to make the registered gap observa
it is covered."* **A two-node keep-oldest mesh has an acknowledged total-outage hole.** If OtOpcUa
adopts 2-node meshes, this must be decided deliberately, not inherited.
> **CLOSED 2026-07-22.** The `InitJoin` half of this gap is fixed in both repos by the self-form
> fallback: `Cluster:SelfFormAfter` (default 10 s) lets a node that is one of its own seeds form a
> cluster on itself when no seed answers. See `docs/Redundancy.md` §"Bootstrap: the self-form
> fallback" — including the island guard that keeps today's non-seed site nodes waiting, which the
> per-cluster mesh removes by making every pair node a seed of its own mesh.
### Both inter-cluster transports are unauthenticated
Akka remoting has no TLS, no secure cookie, no `trusted-selection-paths`. The gRPC listener is h2c
@@ -253,6 +259,14 @@ rather than the configured one. See `docs/Redundancy.md`.
1-vs-1 split, and `docker-dev` is a single six-node mesh. The crash-the-oldest drill therefore lands
with Phase 6/7, which makes every mesh exactly two nodes.
**The bootstrap half of the gap is also closed (2026-07-22).** Downing was only ever one of the two
outage modes: even with `auto-down`, a node cold-starting while its peer was dead looped on `InitJoin`
forever, because Akka lets only the first listed seed form a new cluster. `Cluster:SelfFormAfter`
(default 10 s, `ClusterBootstrapFallback`) now self-forms in that case, guarded so a node absent from
its own seed list never islands itself. Pinned by `SelfFormBootstrapTests`; see `docs/Redundancy.md`
§"Bootstrap: the self-form fallback". Under this design each pair node is a seed of its own two-node
mesh, so the fallback covers both sides and the current site-node exception disappears.
### 6.3 DECIDED — match ScadaBridge's auth posture for now
Inter-cluster transports stay unauthenticated and unencrypted, as theirs are: the boundary assumes a