instar 1.3.628 → 1.3.630
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +133 -5
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +52 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/FencedLease.d.ts +23 -4
- package/dist/core/FencedLease.d.ts.map +1 -1
- package/dist/core/FencedLease.js +44 -4
- package/dist/core/FencedLease.js.map +1 -1
- package/dist/core/HttpLeaseTransport.d.ts +56 -3
- package/dist/core/HttpLeaseTransport.d.ts.map +1 -1
- package/dist/core/HttpLeaseTransport.js +191 -51
- package/dist/core/HttpLeaseTransport.js.map +1 -1
- package/dist/core/LeaseCoordinator.d.ts +84 -0
- package/dist/core/LeaseCoordinator.d.ts.map +1 -1
- package/dist/core/LeaseCoordinator.js +129 -7
- package/dist/core/LeaseCoordinator.js.map +1 -1
- package/dist/core/MachineIdentity.d.ts +11 -0
- package/dist/core/MachineIdentity.d.ts.map +1 -1
- package/dist/core/MachineIdentity.js +22 -0
- package/dist/core/MachineIdentity.js.map +1 -1
- package/dist/core/MeshUrlAdvertiser.d.ts +50 -0
- package/dist/core/MeshUrlAdvertiser.d.ts.map +1 -1
- package/dist/core/MeshUrlAdvertiser.js +127 -0
- package/dist/core/MeshUrlAdvertiser.js.map +1 -1
- package/dist/core/MultiMachineCoordinator.d.ts +87 -0
- package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
- package/dist/core/MultiMachineCoordinator.js +241 -6
- package/dist/core/MultiMachineCoordinator.js.map +1 -1
- package/dist/core/PeerEndpointResolver.d.ts +0 -0
- package/dist/core/PeerEndpointResolver.d.ts.map +1 -0
- package/dist/core/PeerEndpointResolver.js +0 -0
- package/dist/core/PeerEndpointResolver.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +10 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +15 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +131 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +3 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +15 -2
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/machineAuth.d.ts +24 -0
- package/dist/server/machineAuth.d.ts.map +1 -1
- package/dist/server/machineAuth.js +71 -0
- package/dist/server/machineAuth.js.map +1 -1
- package/dist/server/machineRoutes.d.ts +7 -1
- package/dist/server/machineRoutes.d.ts.map +1 -1
- package/dist/server/machineRoutes.js +28 -3
- package/dist/server/machineRoutes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +22 -22
- package/src/scaffold/templates.ts +3 -0
- package/upgrades/1.3.629.md +31 -0
- package/upgrades/1.3.630.md +38 -0
- package/upgrades/side-effects/multi-machine-lease-self-heal.md +45 -0
- package/upgrades/side-effects/multi-transport-mesh-comms.md +70 -0
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* The HTTP layer is injected (fetchImpl) so the broadcast/observe/reachability
|
|
17
17
|
* logic is unit-testable without a network.
|
|
18
18
|
*/
|
|
19
|
-
import { signRequest } from '../server/machineAuth.js';
|
|
19
|
+
import { signRequest, verifyLeaseAck, verifyLeaseAckIdentity, newReqNonce } from '../server/machineAuth.js';
|
|
20
20
|
import { PeerFailureLogGate } from './PeerFailureLogGate.js';
|
|
21
21
|
export class HttpLeaseTransport {
|
|
22
22
|
d;
|
|
@@ -63,34 +63,170 @@ export class HttpLeaseTransport {
|
|
|
63
63
|
this.lastBroadcastOkAt = this.now();
|
|
64
64
|
return true;
|
|
65
65
|
}
|
|
66
|
+
const results = await Promise.all(peers.map((peer) => this.dialPeer(peer, '/api/lease', { lease }, lease.epoch)));
|
|
67
|
+
const anyOk = results.some((r) => r.confirmed);
|
|
68
|
+
if (anyOk)
|
|
69
|
+
this.lastBroadcastOkAt = this.now();
|
|
70
|
+
return anyOk;
|
|
71
|
+
}
|
|
72
|
+
meshOn() {
|
|
73
|
+
if (!this.d.resolver)
|
|
74
|
+
return false;
|
|
75
|
+
return this.d.meshTransportEnabled ? this.d.meshTransportEnabled() : true;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Dial one peer over its resolved endpoints with hedged failover (Decision 3):
|
|
79
|
+
* try the best (last-known-good / due) rope first; after `hedgeDelayMs` fire the
|
|
80
|
+
* remaining ropes in parallel; the first rope that genuinely CONFIRMS wins and
|
|
81
|
+
* the losers are aborted. Confirmation = a verified accept-ack from the expected
|
|
82
|
+
* peer (Decision 9) for an ack-capable peer, else a 2xx (back-compat). When the
|
|
83
|
+
* mesh path is off (no resolver / disabled) it is the legacy single-`url` dial.
|
|
84
|
+
*/
|
|
85
|
+
async dialPeer(peer, path, bodyBase, sentEpoch) {
|
|
66
86
|
const fetchImpl = this.d.fetchImpl ?? fetch;
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
if (!this.meshOn()) {
|
|
88
|
+
return this.legacyDial(peer, path, bodyBase, fetchImpl);
|
|
89
|
+
}
|
|
90
|
+
const resolved = this.d.resolver.resolve(peer.machineId, peer.endpoints, peer.url);
|
|
91
|
+
if (resolved.length === 0)
|
|
92
|
+
return { confirmed: false, lease: null };
|
|
93
|
+
const attempt = async (ep, signal) => {
|
|
94
|
+
const reqNonce = newReqNonce();
|
|
95
|
+
const body = { ...bodyBase, reqNonce };
|
|
96
|
+
const headers = signRequest(this.d.selfMachineId, this.d.signingKeyPem, body, this.d.nextSequence());
|
|
97
|
+
const started = this.now();
|
|
69
98
|
try {
|
|
70
|
-
const
|
|
71
|
-
const headers = signRequest(this.d.selfMachineId, this.d.signingKeyPem, body, this.d.nextSequence());
|
|
72
|
-
const res = await fetchImpl(`${peer.url.replace(/\/$/, '')}/api/lease`, {
|
|
99
|
+
const res = await fetchImpl(`${ep.url.replace(/\/$/, '')}${path}`, {
|
|
73
100
|
method: 'POST',
|
|
74
101
|
headers: { 'Content-Type': 'application/json', ...headers },
|
|
75
102
|
body: JSON.stringify(body),
|
|
76
|
-
|
|
77
|
-
signal: AbortSignal.timeout(this.requestTimeoutMs),
|
|
103
|
+
signal: mergeSignals(signal, AbortSignal.timeout(this.requestTimeoutMs)),
|
|
78
104
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
|
|
105
|
+
const httpOk = !!res && res.ok;
|
|
106
|
+
const data = httpOk ? (await res.json().catch(() => null)) : null;
|
|
107
|
+
const outcome = this.interpretResponse(peer, path, reqNonce, sentEpoch, data, httpOk);
|
|
108
|
+
this.d.resolver.recordResult(peer.machineId, ep.kind, outcome.confirmed, this.now() - started);
|
|
109
|
+
if (outcome.confirmed)
|
|
110
|
+
this.logSuccess(`${path} ${peer.machineId}/${ep.kind}`);
|
|
111
|
+
else
|
|
112
|
+
this.logFailure(`${path} ${peer.machineId}/${ep.kind}`, 'unconfirmed');
|
|
113
|
+
return outcome;
|
|
86
114
|
}
|
|
87
115
|
catch (err) {
|
|
88
|
-
this.
|
|
116
|
+
this.d.resolver.recordResult(peer.machineId, ep.kind, false, this.now() - started);
|
|
117
|
+
this.logFailure(`${path} ${peer.machineId}/${ep.kind}`, err instanceof Error ? err.message : String(err));
|
|
118
|
+
return { confirmed: false, lease: null };
|
|
89
119
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
};
|
|
121
|
+
return this.hedge(resolved, attempt);
|
|
122
|
+
}
|
|
123
|
+
/** Legacy single-`url` dial — byte-for-byte today (2xx = confirmed, no ack). */
|
|
124
|
+
async legacyDial(peer, path, bodyBase, fetchImpl) {
|
|
125
|
+
try {
|
|
126
|
+
const headers = signRequest(this.d.selfMachineId, this.d.signingKeyPem, bodyBase, this.d.nextSequence());
|
|
127
|
+
const res = await fetchImpl(`${peer.url.replace(/\/$/, '')}${path}`, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
130
|
+
body: JSON.stringify(bodyBase),
|
|
131
|
+
signal: AbortSignal.timeout(this.requestTimeoutMs),
|
|
132
|
+
});
|
|
133
|
+
const httpOk = !!res && res.ok;
|
|
134
|
+
if (!httpOk) {
|
|
135
|
+
this.logFailure(`${path} to ${peer.machineId}`, `status ${res?.status}`);
|
|
136
|
+
return { confirmed: false, lease: null };
|
|
137
|
+
}
|
|
138
|
+
this.logSuccess(`${path} to ${peer.machineId}`);
|
|
139
|
+
if (path === '/api/lease/pull') {
|
|
140
|
+
const data = (await res.json().catch(() => null));
|
|
141
|
+
return { confirmed: true, lease: data?.lease ?? null };
|
|
142
|
+
}
|
|
143
|
+
return { confirmed: true, lease: null };
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
this.logFailure(`${path} to ${peer.machineId}`, err instanceof Error ? err.message : String(err));
|
|
147
|
+
return { confirmed: false, lease: null };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Interpret a mesh response (accept-ack semantics, Decision 9). */
|
|
151
|
+
interpretResponse(peer, path, sentReqNonce, sentEpoch, data, httpOk) {
|
|
152
|
+
if (!httpOk)
|
|
153
|
+
return { confirmed: false, lease: null };
|
|
154
|
+
const ackCapable = !!peer.meshAckCapable && !!peer.publicKeyPem;
|
|
155
|
+
if (path === '/api/lease/pull') {
|
|
156
|
+
const folded = data?.lease ?? null;
|
|
157
|
+
if (!ackCapable)
|
|
158
|
+
return { confirmed: true, lease: folded }; // legacy 2xx
|
|
159
|
+
const idOk = verifyLeaseAckIdentity(data?.ack, data?.sig, peer.machineId, sentReqNonce, peer.publicKeyPem);
|
|
160
|
+
return { confirmed: idOk, lease: idOk ? folded : null };
|
|
161
|
+
}
|
|
162
|
+
// /api/lease (broadcast) — epoch-equality confirmation.
|
|
163
|
+
if (!ackCapable)
|
|
164
|
+
return { confirmed: true, lease: null }; // legacy 2xx back-compat
|
|
165
|
+
const verdict = verifyLeaseAck(data?.ack, data?.sig, peer.machineId, sentReqNonce, sentEpoch ?? -1, peer.publicKeyPem);
|
|
166
|
+
// 'higher-epoch' is a real takeover signal — NOT a renewal confirmation.
|
|
167
|
+
return { confirmed: verdict === 'confirmed', lease: null };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Hedged race over an ordered endpoint list: fire endpoint[0] immediately, then
|
|
171
|
+
* after hedgeDelayMs fire the rest in parallel; resolve on the FIRST confirmed
|
|
172
|
+
* (aborting the losers), else return the last outcome once all settle.
|
|
173
|
+
*/
|
|
174
|
+
async hedge(endpoints, attempt) {
|
|
175
|
+
const controller = new AbortController();
|
|
176
|
+
const hedgeMs = this.d.hedgeDelayMs ?? 1500;
|
|
177
|
+
return new Promise((resolve) => {
|
|
178
|
+
let settled = false;
|
|
179
|
+
let pending = 0;
|
|
180
|
+
let last = { confirmed: false, lease: null };
|
|
181
|
+
const finish = (r) => {
|
|
182
|
+
if (settled)
|
|
183
|
+
return;
|
|
184
|
+
settled = true;
|
|
185
|
+
controller.abort();
|
|
186
|
+
clearTimeout(hedgeTimer);
|
|
187
|
+
resolve(r);
|
|
188
|
+
};
|
|
189
|
+
const fire = (ep) => {
|
|
190
|
+
pending += 1;
|
|
191
|
+
attempt(ep, controller.signal)
|
|
192
|
+
.then((r) => {
|
|
193
|
+
last = r;
|
|
194
|
+
if (r.confirmed)
|
|
195
|
+
finish(r);
|
|
196
|
+
})
|
|
197
|
+
.catch(() => { })
|
|
198
|
+
.finally(() => {
|
|
199
|
+
pending -= 1;
|
|
200
|
+
if (!settled && pending === 0 && !firedRest) {
|
|
201
|
+
// first rope settled unconfirmed before the hedge timer → fire the rest now
|
|
202
|
+
fireRest();
|
|
203
|
+
}
|
|
204
|
+
else if (!settled && pending === 0 && firedRest) {
|
|
205
|
+
finish(last);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
let firedRest = false;
|
|
210
|
+
const fireRest = () => {
|
|
211
|
+
if (firedRest)
|
|
212
|
+
return;
|
|
213
|
+
firedRest = true;
|
|
214
|
+
const rest = endpoints.slice(1);
|
|
215
|
+
if (rest.length === 0) {
|
|
216
|
+
if (pending === 0)
|
|
217
|
+
finish(last);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
for (const ep of rest)
|
|
221
|
+
fire(ep);
|
|
222
|
+
};
|
|
223
|
+
const hedgeTimer = setTimeout(() => {
|
|
224
|
+
if (!settled)
|
|
225
|
+
fireRest();
|
|
226
|
+
}, hedgeMs);
|
|
227
|
+
// kick off the best rope
|
|
228
|
+
fire(endpoints[0]);
|
|
229
|
+
});
|
|
94
230
|
}
|
|
95
231
|
observed() {
|
|
96
232
|
return { lease: this.lastObserved, lastNonceByHolder: { ...this.lastNonceByHolder } };
|
|
@@ -108,20 +244,29 @@ export class HttpLeaseTransport {
|
|
|
108
244
|
* machine-auth verification). Keeps only the highest-epoch observed lease and
|
|
109
245
|
* advances the per-holder nonce watermark (replay detection happens in
|
|
110
246
|
* FencedLease.acceptTunnelLease which reads this map).
|
|
247
|
+
*
|
|
248
|
+
* multi-transport-mesh-comms — returns the resulting highest observed epoch (or
|
|
249
|
+
* the just-folded lease's epoch), so the /api/lease receiver can sign a
|
|
250
|
+
* freshness-bound accept-ack proving WHAT it folded (Decision 9). When this
|
|
251
|
+
* machine already holds a HIGHER epoch than the broadcast (a takeover the
|
|
252
|
+
* broadcaster hasn't seen), the returned epoch is that higher value — which the
|
|
253
|
+
* caller reads as a stand-down signal, never a confirmation.
|
|
111
254
|
*/
|
|
112
255
|
recordObserved(lease) {
|
|
113
256
|
if (!lease || typeof lease.epoch !== 'number')
|
|
114
|
-
return;
|
|
257
|
+
return undefined;
|
|
115
258
|
const prevNonce = this.lastNonceByHolder[lease.holder] ?? -1;
|
|
116
259
|
// Only accept a strictly-newer nonce for this holder (drop replays here too).
|
|
117
260
|
if (lease.nonce <= prevNonce && this.lastObserved && this.lastObserved.epoch >= lease.epoch) {
|
|
118
|
-
return;
|
|
261
|
+
return this.lastObserved?.epoch;
|
|
119
262
|
}
|
|
120
263
|
if (lease.nonce > prevNonce)
|
|
121
264
|
this.lastNonceByHolder[lease.holder] = lease.nonce;
|
|
122
265
|
if (!this.lastObserved || lease.epoch >= this.lastObserved.epoch) {
|
|
123
266
|
this.lastObserved = lease;
|
|
124
267
|
}
|
|
268
|
+
// The resulting observed epoch = max(what we held, the folded lease).
|
|
269
|
+
return Math.max(this.lastObserved?.epoch ?? lease.epoch, lease.epoch);
|
|
125
270
|
}
|
|
126
271
|
/**
|
|
127
272
|
* Active PULL (Cross-Machine Coherence): GET a peer's current lease over the
|
|
@@ -137,37 +282,17 @@ export class HttpLeaseTransport {
|
|
|
137
282
|
* returns no lease — proves reachability.
|
|
138
283
|
*/
|
|
139
284
|
async pullPeer(peer) {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
const body = {};
|
|
143
|
-
const headers = signRequest(this.d.selfMachineId, this.d.signingKeyPem, body, this.d.nextSequence());
|
|
144
|
-
const res = await fetchImpl(`${peer.url.replace(/\/$/, '')}/api/lease/pull`, {
|
|
145
|
-
method: 'POST',
|
|
146
|
-
headers: { 'Content-Type': 'application/json', ...headers },
|
|
147
|
-
body: JSON.stringify(body),
|
|
148
|
-
// P19 brake: the pull loop's `leasePulling` guard means a hung socket
|
|
149
|
-
// would wedge ALL future pulls — abort instead.
|
|
150
|
-
signal: AbortSignal.timeout(this.requestTimeoutMs),
|
|
151
|
-
});
|
|
152
|
-
if (!res || !res.ok) {
|
|
153
|
-
this.logFailure(`pull from ${peer.machineId}`, `status ${res?.status}`);
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
const data = (await res.json().catch(() => null));
|
|
157
|
-
// A successful response (even one carrying no lease) proves the medium is live.
|
|
158
|
-
this.lastPullOkAt = this.now();
|
|
159
|
-
this.logSuccess(`pull from ${peer.machineId}`);
|
|
160
|
-
const lease = data?.lease ?? null;
|
|
161
|
-
if (lease && typeof lease.epoch === 'number') {
|
|
162
|
-
this.recordObserved(lease);
|
|
163
|
-
return lease;
|
|
164
|
-
}
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
catch (err) {
|
|
168
|
-
this.logFailure(`pull from ${peer.machineId}`, err instanceof Error ? err.message : String(err));
|
|
285
|
+
const outcome = await this.dialPeer(peer, '/api/lease/pull', {}, null);
|
|
286
|
+
if (!outcome.confirmed)
|
|
169
287
|
return null;
|
|
288
|
+
// A confirmed pull (verified reachability) proves the medium is live.
|
|
289
|
+
this.lastPullOkAt = this.now();
|
|
290
|
+
const lease = outcome.lease;
|
|
291
|
+
if (lease && typeof lease.epoch === 'number') {
|
|
292
|
+
this.recordObserved(lease);
|
|
293
|
+
return lease;
|
|
170
294
|
}
|
|
295
|
+
return null;
|
|
171
296
|
}
|
|
172
297
|
/**
|
|
173
298
|
* Best-effort fan-out pull of every peer's lease. Failures are advisory (a peer
|
|
@@ -181,4 +306,19 @@ export class HttpLeaseTransport {
|
|
|
181
306
|
await Promise.all(peers.map((p) => this.pullPeer(p).catch(() => null)));
|
|
182
307
|
}
|
|
183
308
|
}
|
|
309
|
+
/** Combine two AbortSignals — aborts when either does (Node 20.3+ AbortSignal.any, with fallback). */
|
|
310
|
+
function mergeSignals(a, b) {
|
|
311
|
+
const anyFn = AbortSignal.any;
|
|
312
|
+
if (typeof anyFn === 'function')
|
|
313
|
+
return anyFn([a, b]);
|
|
314
|
+
const c = new AbortController();
|
|
315
|
+
const onAbort = () => c.abort();
|
|
316
|
+
if (a.aborted || b.aborted)
|
|
317
|
+
c.abort();
|
|
318
|
+
else {
|
|
319
|
+
a.addEventListener('abort', onAbort, { once: true });
|
|
320
|
+
b.addEventListener('abort', onAbort, { once: true });
|
|
321
|
+
}
|
|
322
|
+
return c.signal;
|
|
323
|
+
}
|
|
184
324
|
//# sourceMappingURL=HttpLeaseTransport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpLeaseTransport.js","sourceRoot":"","sources":["../../src/core/HttpLeaseTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AA2C7D,MAAM,OAAO,kBAAkB;IACZ,CAAC,CAAyB;IACnC,YAAY,GAAuB,IAAI,CAAC;IACxC,iBAAiB,GAA2B,EAAE,CAAC;IAC/C,iBAAiB,GAAG,CAAC,CAAC;IACtB,YAAY,GAAG,CAAC,CAAC;IACR,QAAQ,CAAS;IACjB,gBAAgB,CAAS;IAC1C,6EAA6E;IAC5D,OAAO,CAAqB;IAE7C,YAAY,IAA4B;QACtC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACd,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,oBAAoB,IAAI,MAAM,CAAC;QACpD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,MAAM,CAAC;QACxD,IAAI,CAAC,OAAO,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;IACtE,CAAC;IAED,uFAAuF;IAC/E,UAAU,CAAC,GAAW,EAAE,MAAc;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IACO,UAAU,CAAC,GAAW;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEO,GAAG;QACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACpC,CAAC;IACO,GAAG,CAAC,CAAS;QACnB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,KAAkB;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,4EAA4E;YAC5E,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;gBACrG,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,EAAE;oBACtE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE;oBAC3D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAC1B,sEAAsE;oBACtE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC;iBACnD,CAAC,CAAC;gBACH,IAAI,GAAG,IAAK,GAAgB,CAAC,EAAE,EAAE,CAAC;oBAChC,KAAK,GAAG,IAAI,CAAC;oBACb,IAAI,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBACpD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,SAAS,EAAE,EAAE,UAAW,GAAgB,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC3F,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACtG,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QACF,IAAI,KAAK;YAAE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ;QACN,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,EAAE,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;IACxF,CAAC;IAED,WAAW;QACT,iFAAiF;QACjF,4EAA4E;QAC5E,gFAAgF;QAChF,mCAAmC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,KAAkB;QAC/B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7D,8EAA8E;QAC9E,IAAI,KAAK,CAAC,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5F,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS;YAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QAChF,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YACjE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAe;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;YACrG,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,EAAE;gBAC3E,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE;gBAC3D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,sEAAsE;gBACtE,gDAAgD;gBAChD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC;aACnD,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,IAAI,CAAE,GAAgB,CAAC,EAAE,EAAE,CAAC;gBAClC,IAAI,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,SAAS,EAAE,EAAE,UAAW,GAAgB,EAAE,MAAM,EAAE,CAAC,CAAC;gBACtF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,MAAO,GAAgB,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAA0C,CAAC;YACzG,gFAAgF;YAChF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC;YAClC,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC7C,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBAC3B,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"HttpLeaseTransport.js","sourceRoot":"","sources":["../../src/core/HttpLeaseTransport.ts"],"names":[],"mappings":"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"}
|
|
@@ -119,6 +119,42 @@ export interface LeaseCoordinatorDeps {
|
|
|
119
119
|
onSelfSuspend?: (reason: string) => void;
|
|
120
120
|
/** Fired whenever our effective epoch advances (drives leaseEpochChange → registry push). */
|
|
121
121
|
onEpochAdvance?: (epoch: number) => void;
|
|
122
|
+
/**
|
|
123
|
+
* F2 (multi-machine-lease-self-heal staleHolderTakeover) — resolved live so a
|
|
124
|
+
* config flip needs no restart. null/disabled ⇒ canAcquire is byte-for-byte the
|
|
125
|
+
* legacy behavior. When enabled, a standby may take over a holder whose signed
|
|
126
|
+
* nonce watermark hasn't advanced for `ttlMs × nonRenewalMissedObservations` of
|
|
127
|
+
* the OBSERVER's own monotonic time (skew-immune; the takeover stays CAS-fenced).
|
|
128
|
+
*/
|
|
129
|
+
staleHolderTakeover?: () => {
|
|
130
|
+
enabled: boolean;
|
|
131
|
+
nonRenewalMissedObservations: number;
|
|
132
|
+
} | null;
|
|
133
|
+
/**
|
|
134
|
+
* multi-transport-mesh-comms Layer 3 (soloCaptainHold) — resolved live; DARK by
|
|
135
|
+
* default (null/disabled ⇒ renew() is byte-for-byte today's self-fence). When
|
|
136
|
+
* enabled AND all three preconditions hold, a preferred stationary captain that
|
|
137
|
+
* cannot confirm its renewal over ANY rope HOLDS its lease (same epoch) instead
|
|
138
|
+
* of self-suspending. The preconditions are SIGNALS consumed here, never
|
|
139
|
+
* authority invented here:
|
|
140
|
+
* - isPreferredAwakeAgreed(): this machine is the F4-agreed preferred-awake
|
|
141
|
+
* machine (NOT a raw-config read — the agreement signal from the coordinator).
|
|
142
|
+
* - allPeersPresumedGone(): every peer is presumed-gone by liveness-silence
|
|
143
|
+
* (the EXISTING presumedDeadHolders timeout), i.e. positively aged-out, not
|
|
144
|
+
* merely unreachable this tick.
|
|
145
|
+
* - no higher epoch observed (checked inline against the effective view).
|
|
146
|
+
* The monotonic self-fence stays armed whenever allPeersPresumedGone() is false,
|
|
147
|
+
* so a merely-unreachable-but-recently-alive peer can NEVER keep the captain
|
|
148
|
+
* alive — only a liveness-aged-out one can. store.refresh is NOT used as
|
|
149
|
+
* evidence (a tautology on LocalLeaseStore). Spec: docs/specs/multi-transport-mesh-comms.md.
|
|
150
|
+
*/
|
|
151
|
+
soloCaptainHold?: () => {
|
|
152
|
+
enabled: boolean;
|
|
153
|
+
} | null;
|
|
154
|
+
/** F4-agreed preferred-awake signal (consumed by Layer 3 — never the raw config). */
|
|
155
|
+
isPreferredAwakeAgreed?: () => boolean;
|
|
156
|
+
/** True iff EVERY peer is presumed-gone by liveness-silence (Layer 3 gate). */
|
|
157
|
+
allPeersPresumedGone?: () => boolean;
|
|
122
158
|
logger?: (msg: string) => void;
|
|
123
159
|
}
|
|
124
160
|
export declare class LeaseCoordinator {
|
|
@@ -143,6 +179,17 @@ export declare class LeaseCoordinator {
|
|
|
143
179
|
* while it is not superseded by a higher epoch.
|
|
144
180
|
*/
|
|
145
181
|
private selfIssued;
|
|
182
|
+
/**
|
|
183
|
+
* F2 (staleHolderTakeover) — per-holder freshness on the OBSERVER's own
|
|
184
|
+
* monotonic clock: the time we last saw that holder's signed nonce watermark
|
|
185
|
+
* ADVANCE (a renewing holder bumps its nonce each renew). Stamped only when a
|
|
186
|
+
* VERIFIED observed lease's nonce strictly exceeds the last we recorded for
|
|
187
|
+
* that holder. `lastObservedNonce` is the per-holder high-water nonce that
|
|
188
|
+
* gates the stamp. Single-clock ⇒ clock-skew immune; the holder cannot forge
|
|
189
|
+
* freshness (the nonce is inside its Ed25519 signature).
|
|
190
|
+
*/
|
|
191
|
+
private freshObservedMonoMs;
|
|
192
|
+
private lastObservedNonce;
|
|
146
193
|
constructor(deps: LeaseCoordinatorDeps);
|
|
147
194
|
private now;
|
|
148
195
|
/**
|
|
@@ -172,6 +219,25 @@ export declare class LeaseCoordinator {
|
|
|
172
219
|
/** The current effective epoch (for stamping writes/sends). */
|
|
173
220
|
currentEpoch(): number;
|
|
174
221
|
currentHolder(): string | null;
|
|
222
|
+
/**
|
|
223
|
+
* F4 — is `machineId` the current holder of a LIVE (non-expired, non-released)
|
|
224
|
+
* lease we observe? The deferential-standby health gate: a non-preferred machine
|
|
225
|
+
* defers to its preferred peer ONLY while this is true, so a frozen/down/released
|
|
226
|
+
* preferred never strands coverage (the non-preferred then acquires normally).
|
|
227
|
+
*/
|
|
228
|
+
isHolderHealthy(machineId: string): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* multi-transport-mesh-comms Layer 3 — may a preferred stationary captain HOLD
|
|
231
|
+
* its lease (same epoch) instead of self-suspending when no rope confirmed?
|
|
232
|
+
* ALL must hold (each is an EXISTING signal, never authority invented here):
|
|
233
|
+
* (1) the feature is enabled (DARK by default);
|
|
234
|
+
* (2) this machine is the F4-AGREED preferred-awake machine;
|
|
235
|
+
* (3) EVERY peer is presumed-gone by liveness-silence (aged out, not merely
|
|
236
|
+
* unreachable this tick) — the load-bearing "absent vs unreachable" gate;
|
|
237
|
+
* (4) no higher epoch than ours is observed (a real takeover always wins).
|
|
238
|
+
* Fail-closed: a missing dep ⇒ not eligible (today's self-suspend).
|
|
239
|
+
*/
|
|
240
|
+
private soloCaptainHoldEligible;
|
|
175
241
|
/**
|
|
176
242
|
* The current effective-view signed lease (max of tunnel-observed, git-committed,
|
|
177
243
|
* and this machine's self-issued renewal), or null. Used to SERVE an active PULL
|
|
@@ -199,6 +265,24 @@ export declare class LeaseCoordinator {
|
|
|
199
265
|
* win after we relinquish.
|
|
200
266
|
*/
|
|
201
267
|
relinquish(): void;
|
|
268
|
+
/**
|
|
269
|
+
* F2 — build the StaleHolderTakeoverOpts for `canAcquire`, or `undefined` when
|
|
270
|
+
* the flag is off / the candidate is not a takeable peer (so canAcquire stays
|
|
271
|
+
* byte-for-byte the legacy behavior). Uses this holder's observed freshness on
|
|
272
|
+
* the OBSERVER's own monotonic clock.
|
|
273
|
+
*/
|
|
274
|
+
private staleHolderOpts;
|
|
275
|
+
/**
|
|
276
|
+
* F3 — relinquish a lease THIS machine holds AND broadcast a SIGNED tombstone
|
|
277
|
+
* so peers stop deferring to a muted ex-holder's zombie. Called level-triggered
|
|
278
|
+
* by the coordinator when this machine is observe-only yet still the named
|
|
279
|
+
* holder (the 2026-06-19 silent-standby zombie). The tombstone is
|
|
280
|
+
* `released:true` at our epoch with a fresh nonce strictly greater than our last
|
|
281
|
+
* (so a concurrent in-flight renewal cannot out-nonce it) and a past expiry; a
|
|
282
|
+
* higher-epoch normal takeover always strictly dominates it. Idempotent: a no-op
|
|
283
|
+
* (just local relinquish) when we are not the named holder.
|
|
284
|
+
*/
|
|
285
|
+
relinquishAndBroadcast(): Promise<void>;
|
|
202
286
|
/**
|
|
203
287
|
* Force a ONE-TIME epoch advance to resolve a same-epoch contested tie (spec
|
|
204
288
|
* §Problem A — the WINNER side, lower `machineId`). Unlike acquireIfEligible(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LeaseCoordinator.d.ts","sourceRoot":"","sources":["../../src/core/LeaseCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"LeaseCoordinator.d.ts","sourceRoot":"","sources":["../../src/core/LeaseCoordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,17 @@ export class LeaseCoordinator {
|
|
|
41
41
|
* while it is not superseded by a higher epoch.
|
|
42
42
|
*/
|
|
43
43
|
selfIssued = null;
|
|
44
|
+
/**
|
|
45
|
+
* F2 (staleHolderTakeover) — per-holder freshness on the OBSERVER's own
|
|
46
|
+
* monotonic clock: the time we last saw that holder's signed nonce watermark
|
|
47
|
+
* ADVANCE (a renewing holder bumps its nonce each renew). Stamped only when a
|
|
48
|
+
* VERIFIED observed lease's nonce strictly exceeds the last we recorded for
|
|
49
|
+
* that holder. `lastObservedNonce` is the per-holder high-water nonce that
|
|
50
|
+
* gates the stamp. Single-clock ⇒ clock-skew immune; the holder cannot forge
|
|
51
|
+
* freshness (the nonce is inside its Ed25519 signature).
|
|
52
|
+
*/
|
|
53
|
+
freshObservedMonoMs = new Map();
|
|
54
|
+
lastObservedNonce = new Map();
|
|
44
55
|
constructor(deps) {
|
|
45
56
|
this.d = deps;
|
|
46
57
|
this.fl = deps.lease;
|
|
@@ -103,9 +114,20 @@ export class LeaseCoordinator {
|
|
|
103
114
|
const { [obs.lease.holder]: _self, ...nonceFloor } = obs.lastNonceByHolder;
|
|
104
115
|
void _self;
|
|
105
116
|
const decision = this.fl.acceptTunnelLease(obs.lease, git.epoch, nonceFloor);
|
|
106
|
-
if (decision.accept
|
|
107
|
-
|
|
108
|
-
epoch
|
|
117
|
+
if (decision.accept) {
|
|
118
|
+
// F2 freshness stamp (VERIFIED fold-in): a renewing holder bumps its
|
|
119
|
+
// signed nonce each renew (same OR higher epoch), so its watermark
|
|
120
|
+
// advances; a non-renewing holder's stops. Stamp the OBSERVER's own
|
|
121
|
+
// monotonic time when a peer holder's nonce watermark strictly advances.
|
|
122
|
+
const prevNonce = this.lastObservedNonce.get(obs.lease.holder) ?? -1;
|
|
123
|
+
if (obs.lease.holder !== this.selfMachineId && obs.lease.nonce > prevNonce) {
|
|
124
|
+
this.lastObservedNonce.set(obs.lease.holder, obs.lease.nonce);
|
|
125
|
+
this.freshObservedMonoMs.set(obs.lease.holder, this.monotonicNow());
|
|
126
|
+
}
|
|
127
|
+
if (obs.lease.epoch > epoch) {
|
|
128
|
+
bestLease = obs.lease;
|
|
129
|
+
epoch = obs.lease.epoch;
|
|
130
|
+
}
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
133
|
}
|
|
@@ -140,7 +162,50 @@ export class LeaseCoordinator {
|
|
|
140
162
|
return this.effectiveView().epoch;
|
|
141
163
|
}
|
|
142
164
|
currentHolder() {
|
|
143
|
-
|
|
165
|
+
const lease = this.effectiveView().lease;
|
|
166
|
+
// F3 — a RELEASED tombstone declares "epoch N released, not held": it names
|
|
167
|
+
// no live holder, so peers stop deferring to a muted ex-holder's zombie. A
|
|
168
|
+
// higher-epoch normal acquisition still strictly dominates (epoch fold).
|
|
169
|
+
if (!lease || lease.released)
|
|
170
|
+
return null;
|
|
171
|
+
return lease.holder;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* F4 — is `machineId` the current holder of a LIVE (non-expired, non-released)
|
|
175
|
+
* lease we observe? The deferential-standby health gate: a non-preferred machine
|
|
176
|
+
* defers to its preferred peer ONLY while this is true, so a frozen/down/released
|
|
177
|
+
* preferred never strands coverage (the non-preferred then acquires normally).
|
|
178
|
+
*/
|
|
179
|
+
isHolderHealthy(machineId) {
|
|
180
|
+
const view = this.effectiveView();
|
|
181
|
+
if (!view.lease || view.lease.released || view.lease.holder !== machineId)
|
|
182
|
+
return false;
|
|
183
|
+
return !this.fl.isExpired(view.lease, this.now());
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* multi-transport-mesh-comms Layer 3 — may a preferred stationary captain HOLD
|
|
187
|
+
* its lease (same epoch) instead of self-suspending when no rope confirmed?
|
|
188
|
+
* ALL must hold (each is an EXISTING signal, never authority invented here):
|
|
189
|
+
* (1) the feature is enabled (DARK by default);
|
|
190
|
+
* (2) this machine is the F4-AGREED preferred-awake machine;
|
|
191
|
+
* (3) EVERY peer is presumed-gone by liveness-silence (aged out, not merely
|
|
192
|
+
* unreachable this tick) — the load-bearing "absent vs unreachable" gate;
|
|
193
|
+
* (4) no higher epoch than ours is observed (a real takeover always wins).
|
|
194
|
+
* Fail-closed: a missing dep ⇒ not eligible (today's self-suspend).
|
|
195
|
+
*/
|
|
196
|
+
soloCaptainHoldEligible(ourEpoch) {
|
|
197
|
+
const cfg = this.d.soloCaptainHold?.();
|
|
198
|
+
if (!cfg?.enabled)
|
|
199
|
+
return false;
|
|
200
|
+
if (!this.d.isPreferredAwakeAgreed?.())
|
|
201
|
+
return false;
|
|
202
|
+
if (!this.d.allPeersPresumedGone?.())
|
|
203
|
+
return false;
|
|
204
|
+
// No higher epoch observed than the one we hold (a real takeover dominates).
|
|
205
|
+
const view = this.effectiveView();
|
|
206
|
+
if (view.epoch > ourEpoch)
|
|
207
|
+
return false;
|
|
208
|
+
return true;
|
|
144
209
|
}
|
|
145
210
|
/**
|
|
146
211
|
* The current effective-view signed lease (max of tunnel-observed, git-committed,
|
|
@@ -175,6 +240,48 @@ export class LeaseCoordinator {
|
|
|
175
240
|
this.d.store.forceLocalExpiry?.();
|
|
176
241
|
this.log('relinquished self-lease (contested tie-break loser) — winner may now advance to N+1');
|
|
177
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* F2 — build the StaleHolderTakeoverOpts for `canAcquire`, or `undefined` when
|
|
245
|
+
* the flag is off / the candidate is not a takeable peer (so canAcquire stays
|
|
246
|
+
* byte-for-byte the legacy behavior). Uses this holder's observed freshness on
|
|
247
|
+
* the OBSERVER's own monotonic clock.
|
|
248
|
+
*/
|
|
249
|
+
staleHolderOpts(currentLease) {
|
|
250
|
+
const cfg = this.d.staleHolderTakeover?.();
|
|
251
|
+
if (!cfg?.enabled)
|
|
252
|
+
return undefined;
|
|
253
|
+
if (!currentLease || currentLease.holder === this.selfMachineId)
|
|
254
|
+
return undefined;
|
|
255
|
+
return {
|
|
256
|
+
monotonicNowMs: this.monotonicNow(),
|
|
257
|
+
freshObservedMonoMs: this.freshObservedMonoMs.get(currentLease.holder),
|
|
258
|
+
nonRenewalThresholdMs: this.fl.ttlMs * Math.max(1, cfg.nonRenewalMissedObservations),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* F3 — relinquish a lease THIS machine holds AND broadcast a SIGNED tombstone
|
|
263
|
+
* so peers stop deferring to a muted ex-holder's zombie. Called level-triggered
|
|
264
|
+
* by the coordinator when this machine is observe-only yet still the named
|
|
265
|
+
* holder (the 2026-06-19 silent-standby zombie). The tombstone is
|
|
266
|
+
* `released:true` at our epoch with a fresh nonce strictly greater than our last
|
|
267
|
+
* (so a concurrent in-flight renewal cannot out-nonce it) and a past expiry; a
|
|
268
|
+
* higher-epoch normal takeover always strictly dominates it. Idempotent: a no-op
|
|
269
|
+
* (just local relinquish) when we are not the named holder.
|
|
270
|
+
*/
|
|
271
|
+
async relinquishAndBroadcast() {
|
|
272
|
+
const view = this.effectiveView();
|
|
273
|
+
if (!view.lease || view.lease.holder !== this.selfMachineId || view.lease.released) {
|
|
274
|
+
// Not the live holder (or already a tombstone) → just clear local state.
|
|
275
|
+
this.relinquish();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const tombstone = this.fl.signLease(view.lease.epoch, view.lease.acquiredAt, new Date(this.now()).toISOString(), // past/now expiry — released regardless
|
|
279
|
+
this.nextNonce(), // strictly > our last renewal nonce
|
|
280
|
+
true);
|
|
281
|
+
this.relinquish(); // clear our own self-hold first (forceLocalExpiry preserves the epoch floor)
|
|
282
|
+
await this.broadcast(tombstone);
|
|
283
|
+
this.log(`relinquished + broadcast tombstone for epoch ${view.lease.epoch} (silent-standby release)`);
|
|
284
|
+
}
|
|
178
285
|
/**
|
|
179
286
|
* Force a ONE-TIME epoch advance to resolve a same-epoch contested tie (spec
|
|
180
287
|
* §Problem A — the WINNER side, lower `machineId`). Unlike acquireIfEligible(),
|
|
@@ -284,7 +391,7 @@ export class LeaseCoordinator {
|
|
|
284
391
|
if (view.lease && view.lease.holder === this.selfMachineId && !this.fl.isExpired(view.lease, this.now())) {
|
|
285
392
|
return this.renew();
|
|
286
393
|
}
|
|
287
|
-
const decision = this.fl.canAcquire(view.lease, dead, this.now());
|
|
394
|
+
const decision = this.fl.canAcquire(view.lease, dead, this.now(), this.staleHolderOpts(view.lease));
|
|
288
395
|
if (!decision.can) {
|
|
289
396
|
this.log(`acquire skipped: ${decision.reason}`);
|
|
290
397
|
return false;
|
|
@@ -304,8 +411,8 @@ export class LeaseCoordinator {
|
|
|
304
411
|
if (observedEpoch >= candidate.epoch) {
|
|
305
412
|
this.log(`CAS lost to epoch ${observedEpoch} (our candidate ${candidate.epoch}) — yielding`);
|
|
306
413
|
this.emitEpoch(observedEpoch);
|
|
307
|
-
// If the winner is a presumed-dead/expired holder we'll retry; else stop.
|
|
308
|
-
if (!this.fl.canAcquire(res.observed.lease, dead, this.now()).can)
|
|
414
|
+
// If the winner is a presumed-dead/expired/non-renewing holder we'll retry; else stop.
|
|
415
|
+
if (!this.fl.canAcquire(res.observed.lease, dead, this.now(), this.staleHolderOpts(res.observed.lease)).can)
|
|
309
416
|
return false;
|
|
310
417
|
}
|
|
311
418
|
retries++;
|
|
@@ -382,6 +489,21 @@ export class LeaseCoordinator {
|
|
|
382
489
|
this.markRenewOk();
|
|
383
490
|
return true;
|
|
384
491
|
}
|
|
492
|
+
// ── multi-transport-mesh-comms Layer 3 — safe-by-construction solo-captain hold ──
|
|
493
|
+
// The renewal could not confirm over any rope. BEFORE self-suspending, check the
|
|
494
|
+
// partition floor: a PREFERRED stationary captain whose sole peer is PROVABLY
|
|
495
|
+
// GONE (presumed-gone by liveness-silence) holds its lease (same epoch) instead
|
|
496
|
+
// of thrashing. Gated on F4-agreed-preferred + every-peer-presumed-gone + no
|
|
497
|
+
// higher epoch observed. The hold NEVER advances the epoch or takes over a
|
|
498
|
+
// peer's lease, so even a wrongly-presumed-gone live peer cannot double-write
|
|
499
|
+
// (the intact epoch-CAS + signature fence remains the authority). The monotonic
|
|
500
|
+
// self-fence stays armed whenever the presumed-gone gate is NOT satisfied.
|
|
501
|
+
if (this.soloCaptainHoldEligible(view.epoch)) {
|
|
502
|
+
this.selfIssued = renewed;
|
|
503
|
+
this.markRenewOk(); // hold the SAME epoch — no re-acquire, no inflation
|
|
504
|
+
this.log('solo-captain hold: preferred + all peers presumed-gone + no higher epoch — held lease without medium confirm');
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
385
507
|
if (this.monotonicNow() - this.lastRenewOkMonoMs > this.fl.ttlMs) {
|
|
386
508
|
this.suspended = true;
|
|
387
509
|
this.d.onSelfSuspend?.(`could not confirm lease over ${this.d.tunnel ? 'tunnel' : 'git'} for > leaseTtlMs (${this.fl.ttlMs}ms, monotonic) — lease lapsed`);
|