1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! Witness runtime profile (issue #836, PRD #819, ADR 0030).
//!
//! A **witness** is a node that runs *only* the control-plane supervisor —
//! the vote path of the [election core](super::election) — and boots **no
//! data plane** (no storage engine, no WAL, no replication streaming). It
//! holds no data and can never be promoted to primary, but its vote counts
//! toward the election quorum. This makes `2 data nodes + 1 witness` a valid
//! HA shape (the Mongo "arbiter" idea), so an operator gets automatic
//! failover without standing up a third *data* replica.
//!
//! ADR 0030 fixes the shape: "*The supervisor is therefore a module every
//! node runs; a witness is a node that runs only that module.*" and
//! "*Witness members require a build/runtime profile that excludes the data
//! plane.*" This module is that profile.
//!
//! ## What a witness is, structurally
//!
//! * [`RuntimeProfile`] — the boot-time choice between a data-bearing node
//! ([`RuntimeProfile::Data`], supervisor + data plane) and a witness
//! ([`RuntimeProfile::Witness`], supervisor only). `boots_data_plane()` is
//! the one bit the boot pipeline branches on.
//! * [`WitnessSupervisor`] — a booted witness. It is exactly a durable
//! [`Voter`](super::election::Voter) plus the node's shared
//! [`NodeIdentity`](crate::cluster::NodeIdentity); there is, by
//! construction, nothing else. The absence of a data-plane field *is* the
//! guarantee — a witness cannot accidentally serve a read or accept a
//! write because it holds no engine to do so.
//!
//! ## Shared identity, not a second namespace
//!
//! A witness authenticates with the **same per-node mTLS identity** a data
//! member uses: [`NodeIdentity`](crate::cluster::NodeIdentity) is the
//! validated X.509 subject of the node certificate, and the same type backs
//! both [`ReplicationPeerIdentity`](crate::cluster::ReplicationPeerIdentity)
//! and [`ClusterVoterIdentity`](crate::cluster::ClusterVoterIdentity). The
//! witness's membership id is that identity's subject, so its votes land in
//! the same identity namespace as every data member's acks — a witness is
//! not a second-class peer with a parallel auth path.
use PathBuf;
use crateNodeIdentity;
use ;
/// Which planes a node boots.
///
/// Every node runs the control-plane supervisor (the vote path). The profile
/// decides whether the *data plane* — storage engine, WAL, replication
/// streaming — is constructed alongside it.
/// A booted witness node: the control-plane supervisor with no data plane.
///
/// A witness is a [`Voter`] over a durable last-vote store plus the node's
/// shared [`NodeIdentity`] — and nothing else. There is intentionally no
/// engine, no WAL, and no replication handle on this struct: a witness
/// *cannot* serve data because it holds none.
///
/// The store type is generic so production uses the durable
/// [`FileLastVoteStore`] (ADR 0030: "the supervisor needs durable per-node
/// vote state to prevent double-voting across restarts") while tests use an
/// in-memory store.