@mmmbuto/nexuscrew 0.8.20 → 0.8.21
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/frontend/dist/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<meta name="apple-mobile-web-app-title" content="NexusCrew" />
|
|
12
12
|
<link rel="manifest" href="/manifest.json" />
|
|
13
13
|
<title>NexusCrew</title>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-DaFQbMHq.js"></script>
|
|
15
15
|
<link rel="stylesheet" crossorigin href="/assets/index-DQbVJLji.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.8.
|
|
1
|
+
{"version":"0.8.21"}
|
package/lib/nodes/tunnel.js
CHANGED
|
@@ -186,6 +186,14 @@ function openTunnelLog(home, name) {
|
|
|
186
186
|
function classifySshFailure(text, remotePort) {
|
|
187
187
|
const s = String(text || '');
|
|
188
188
|
const target = store.isPort(remotePort) ? `127.0.0.1:${remotePort}` : 'la porta NexusCrew richiesta';
|
|
189
|
+
const reverseMatch = s.match(/remote port forwarding failed for listen port\s+(\d+)/i)
|
|
190
|
+
|| s.match(/(?:bind|listen)[^\r\n]*127\.0\.0\.1:(\d+)/i);
|
|
191
|
+
const reverseListenPort = reverseMatch ? Number(reverseMatch[1]) : null;
|
|
192
|
+
const reverseTarget = store.isPort(reverseListenPort)
|
|
193
|
+
? `127.0.0.1:${reverseListenPort}` : 'la porta reverse negoziata';
|
|
194
|
+
const reversePolicy = store.isPort(reverseListenPort)
|
|
195
|
+
? `che la chiave SSH autorizzi permitlisten="${reverseTarget}"`
|
|
196
|
+
: 'che la chiave SSH autorizzi il reverse listen negoziato';
|
|
189
197
|
if (/administratively prohibited|request (?:was )?denied|open failed:.*prohibited|port forwarding.*(?:disabled|denied)/i.test(s)) {
|
|
190
198
|
return {
|
|
191
199
|
code: 'forward-denied',
|
|
@@ -219,7 +227,7 @@ function classifySshFailure(text, remotePort) {
|
|
|
219
227
|
return {
|
|
220
228
|
code: 'reverse-forward-failed',
|
|
221
229
|
detail: 'il canale inverso non è stato aperto dal nodo hub',
|
|
222
|
-
hint:
|
|
230
|
+
hint: `verifica che ${reverseTarget} non sia occupata e ${reversePolicy}; controlla anche AllowTcpForwarding sul nodo hub`,
|
|
223
231
|
};
|
|
224
232
|
}
|
|
225
233
|
if (/Could not request local forwarding|Address already in use/i.test(s)) {
|
package/lib/settings/routes.js
CHANGED
|
@@ -530,18 +530,16 @@ function settingsRoutes(deps = {}) {
|
|
|
530
530
|
let persistedDesired = wasShared;
|
|
531
531
|
const fetchImpl = seams.fetchImpl || fetch;
|
|
532
532
|
const notifyHub = (shared) => notifyHubShare({ node, shared, fetchImpl, timeoutMs: 5000 });
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
st = nodesStore.updateNode(st, name, { shared });
|
|
536
|
-
nodesStore.atomicWriteStore(nodesPath, st);
|
|
537
|
-
persistedDesired = shared;
|
|
538
|
-
node = nodesStore.getNode(st, name);
|
|
539
|
-
nodesTunnel.stopTunnel({ home, name });
|
|
533
|
+
const ensureLocal = async ({ restart = false } = {}) => {
|
|
534
|
+
if (restart) nodesTunnel.stopTunnel({ home, name });
|
|
540
535
|
const started = nodesTunnel.startForward({
|
|
541
536
|
home, node, localAppPort: runtimePort(),
|
|
542
537
|
spawnImpl: seams.spawnImpl, spawnSyncImpl: seams.spawnSyncImpl,
|
|
543
538
|
sshBin: seams.sshBin, logFd: seams.logFd,
|
|
544
539
|
});
|
|
540
|
+
// startForward is spec-aware: an exact live argv is idempotent, while a
|
|
541
|
+
// stale pre-upgrade supervisor whose -L/-R no longer matches nodes.json
|
|
542
|
+
// is replaced. This is the recovery path for store=false + stale -R.
|
|
545
543
|
if (!started.started && started.reason !== 'already running') {
|
|
546
544
|
throw new Error(started.reason || 'avvio SSH fallito');
|
|
547
545
|
}
|
|
@@ -552,12 +550,28 @@ function settingsRoutes(deps = {}) {
|
|
|
552
550
|
});
|
|
553
551
|
if (!ready || ready.status !== 'healthy') {
|
|
554
552
|
const diagnosis = (seams.readTunnelDiagnostic || nodesTunnel.readTunnelDiagnostic)(home, name, node.remotePort);
|
|
555
|
-
|
|
553
|
+
const failure = new Error((diagnosis && diagnosis.detail) || (ready && ready.detail) || 'hub non raggiungibile dopo il riavvio SSH');
|
|
554
|
+
if (diagnosis && typeof diagnosis.hint === 'string') failure.hint = diagnosis.hint;
|
|
555
|
+
throw failure;
|
|
556
556
|
}
|
|
557
|
+
return started;
|
|
558
|
+
};
|
|
559
|
+
const applyLocal = async (shared) => {
|
|
560
|
+
st = nodesStore.loadStoreStrict(nodesPath);
|
|
561
|
+
st = nodesStore.updateNode(st, name, { shared });
|
|
562
|
+
nodesStore.atomicWriteStore(nodesPath, st);
|
|
563
|
+
persistedDesired = shared;
|
|
564
|
+
node = nodesStore.getNode(st, name);
|
|
565
|
+
await ensureLocal({ restart: true });
|
|
557
566
|
};
|
|
558
567
|
|
|
559
568
|
try {
|
|
560
569
|
if (node.shared === body.shared) {
|
|
570
|
+
// Persisted intent is not proof of the detached process mode. A stale
|
|
571
|
+
// supervisor can survive an npm upgrade and keep retrying -R even when
|
|
572
|
+
// the store/UI says private. Re-enter the spec-aware start path before
|
|
573
|
+
// reconciling the hub, without rewriting nodes.json.
|
|
574
|
+
await ensureLocal();
|
|
561
575
|
await notifyHub(body.shared);
|
|
562
576
|
return send(res, 200, { name, shared: body.shared, unchanged: true, reconciled: true });
|
|
563
577
|
}
|
|
@@ -578,11 +592,13 @@ function settingsRoutes(deps = {}) {
|
|
|
578
592
|
try { await applyLocal(false); } catch (_) { /* best-effort safe rollback */ }
|
|
579
593
|
}
|
|
580
594
|
const offPersisted = body.shared === false && persistedDesired === false;
|
|
595
|
+
const redact = (value) => String(value || '').replace(/Bearer\s+\S+/gi, 'Bearer ***');
|
|
581
596
|
return send(res, 502, {
|
|
582
597
|
error: body.shared ? 'Share non attivato'
|
|
583
598
|
: offPersisted ? 'Share disattivato localmente; hub non riconciliato' : 'Share non disattivato',
|
|
584
599
|
...(offPersisted ? { shared: false, reconcilePending: true } : {}),
|
|
585
|
-
detail:
|
|
600
|
+
detail: redact(e && e.message || e),
|
|
601
|
+
...(e && typeof e.hint === 'string' ? { hint: redact(e.hint) } : {}),
|
|
586
602
|
});
|
|
587
603
|
}
|
|
588
604
|
});
|