@serfab/cadre-host 1.13.0 → 1.15.0
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/README.md +347 -423
- package/dist/bin/host.d.ts +6 -3
- package/dist/bin/host.js +332 -524
- package/dist/bin/host.js.map +1 -1
- package/dist/bin/join-output.d.ts +56 -0
- package/dist/bin/join-output.js +92 -0
- package/dist/bin/join-output.js.map +1 -0
- package/dist/bin/nat-output.d.ts +54 -0
- package/dist/bin/nat-output.js +138 -0
- package/dist/bin/nat-output.js.map +1 -0
- package/dist/bin/ui-access.d.ts +22 -0
- package/dist/bin/ui-access.js +44 -0
- package/dist/bin/ui-access.js.map +1 -0
- package/dist/hosted/claim-details.d.ts +66 -0
- package/dist/hosted/claim-details.js +60 -0
- package/dist/hosted/claim-details.js.map +1 -0
- package/dist/hosted/hosted-node-service.d.ts +325 -0
- package/dist/hosted/hosted-node-service.js +678 -0
- package/dist/hosted/hosted-node-service.js.map +1 -0
- package/dist/hosted/hosted-node-store.d.ts +40 -0
- package/dist/hosted/hosted-node-store.js +126 -0
- package/dist/hosted/hosted-node-store.js.map +1 -0
- package/dist/{donation/donation-supervisor.d.ts → hosted/hosted-node-supervisor.d.ts} +70 -53
- package/dist/hosted/hosted-node-supervisor.js +396 -0
- package/dist/hosted/hosted-node-supervisor.js.map +1 -0
- package/dist/hosted/hosted-node-watcher.d.ts +95 -0
- package/dist/hosted/hosted-node-watcher.js +260 -0
- package/dist/hosted/hosted-node-watcher.js.map +1 -0
- package/dist/hosted/index.d.ts +16 -0
- package/dist/hosted/index.js +13 -0
- package/dist/hosted/index.js.map +1 -0
- package/dist/hosted/node-status.d.ts +51 -0
- package/dist/hosted/node-status.js +77 -0
- package/dist/hosted/node-status.js.map +1 -0
- package/dist/hosted/types.d.ts +141 -0
- package/dist/hosted/types.js +22 -0
- package/dist/hosted/types.js.map +1 -0
- package/dist/index.d.ts +12 -24
- package/dist/index.js +9 -19
- package/dist/index.js.map +1 -1
- package/dist/installer/config.d.ts +27 -34
- package/dist/installer/config.js +46 -15
- package/dist/installer/config.js.map +1 -1
- package/dist/installer/index.d.ts +9 -19
- package/dist/installer/index.js +21 -85
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/paths.d.ts +0 -2
- package/dist/installer/paths.js +0 -4
- package/dist/installer/paths.js.map +1 -1
- package/dist/installer/wizard.d.ts +12 -9
- package/dist/installer/wizard.js +15 -14
- package/dist/installer/wizard.js.map +1 -1
- package/dist/nat/address-resolver.d.ts +18 -17
- package/dist/nat/address-resolver.js +79 -25
- package/dist/nat/address-resolver.js.map +1 -1
- package/dist/nat/address-watch.d.ts +37 -0
- package/dist/nat/address-watch.js +84 -0
- package/dist/nat/address-watch.js.map +1 -0
- package/dist/nat/ddns/duckdns.d.ts +2 -1
- package/dist/nat/ddns/duckdns.js +5 -1
- package/dist/nat/ddns/duckdns.js.map +1 -1
- package/dist/nat/ddns/index.d.ts +6 -0
- package/dist/nat/ddns/index.js.map +1 -1
- package/dist/nat/index.d.ts +13 -9
- package/dist/nat/index.js +7 -5
- package/dist/nat/index.js.map +1 -1
- package/dist/nat/nat-service.d.ts +220 -77
- package/dist/nat/nat-service.js +653 -239
- package/dist/nat/nat-service.js.map +1 -1
- package/dist/nat/nat-store.d.ts +12 -5
- package/dist/nat/nat-store.js +124 -29
- package/dist/nat/nat-store.js.map +1 -1
- package/dist/nat/network-mode.d.ts +19 -0
- package/dist/nat/network-mode.js +32 -0
- package/dist/nat/network-mode.js.map +1 -0
- package/dist/nat/port-mapper.d.ts +83 -79
- package/dist/nat/port-mapper.js +148 -189
- package/dist/nat/port-mapper.js.map +1 -1
- package/dist/nat/reachability.d.ts +32 -15
- package/dist/nat/reachability.js +110 -22
- package/dist/nat/reachability.js.map +1 -1
- package/dist/nat/types.d.ts +98 -27
- package/dist/nat/types.js +8 -5
- package/dist/nat/types.js.map +1 -1
- package/dist/orchestrator/host-process-orchestrator.d.ts +32 -74
- package/dist/orchestrator/host-process-orchestrator.js +84 -233
- package/dist/orchestrator/host-process-orchestrator.js.map +1 -1
- package/dist/{installer/identity.d.ts → orchestrator/identity-file.d.ts} +5 -5
- package/dist/{installer/identity.js → orchestrator/identity-file.js} +6 -6
- package/dist/orchestrator/identity-file.js.map +1 -0
- package/dist/orchestrator/index.d.ts +2 -3
- package/dist/orchestrator/index.js +1 -1
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/node-identity.d.ts +6 -6
- package/dist/orchestrator/node-identity.js +7 -7
- package/dist/orchestrator/node-identity.js.map +1 -1
- package/dist/orchestrator/port-allocator.d.ts +5 -6
- package/dist/orchestrator/port-allocator.js +9 -11
- package/dist/orchestrator/port-allocator.js.map +1 -1
- package/dist/orchestrator/state-store.d.ts +3 -5
- package/dist/orchestrator/state-store.js +2 -10
- package/dist/orchestrator/state-store.js.map +1 -1
- package/dist/orchestrator/types.d.ts +33 -22
- package/dist/orchestrator/types.js.map +1 -1
- package/dist/package-version.d.ts +1 -0
- package/dist/package-version.js +4 -0
- package/dist/package-version.js.map +1 -0
- package/dist/server/error-handler.d.ts +5 -25
- package/dist/server/error-handler.js +11 -74
- package/dist/server/error-handler.js.map +1 -1
- package/dist/server/events/types.d.ts +7 -11
- package/dist/server/events/types.js +2 -1
- package/dist/server/events/types.js.map +1 -1
- package/dist/server/index.d.ts +11 -37
- package/dist/server/index.js +30 -48
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/hosted-nodes.d.ts +28 -0
- package/dist/server/routes/hosted-nodes.js +68 -0
- package/dist/server/routes/hosted-nodes.js.map +1 -0
- package/dist/server/routes/nat.d.ts +4 -1
- package/dist/server/routes/nat.js +13 -2
- package/dist/server/routes/nat.js.map +1 -1
- package/dist/server/routes/nodes.d.ts +6 -20
- package/dist/server/routes/nodes.js +7 -86
- package/dist/server/routes/nodes.js.map +1 -1
- package/dist/server/routes/settings.d.ts +3 -7
- package/dist/server/routes/settings.js +18 -8
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/status.d.ts +2 -25
- package/dist/server/routes/status.js +3 -43
- package/dist/server/routes/status.js.map +1 -1
- package/dist/server/server.js +8 -8
- package/dist/server/settings-store.d.ts +2 -2
- package/dist/server/settings-store.js +2 -2
- package/dist/server/static.js +1 -2
- package/dist/server/static.js.map +1 -1
- package/dist/ui/assets/index-BHd8CWZA.css +1 -0
- package/dist/ui/assets/index-Ccr2GjPT.js +23 -0
- package/dist/ui/assets/index-Ccr2GjPT.js.map +1 -0
- package/dist/ui/index.html +2 -2
- package/dist/update/index.d.ts +2 -2
- package/dist/update/index.js +2 -2
- package/dist/update/store.d.ts +1 -1
- package/dist/update/store.js +1 -1
- package/dist/update/types.d.ts +1 -1
- package/dist/update/types.js +1 -1
- package/package.json +5 -7
- package/src/__tests__/cli-nat.smoke.test.ts +219 -212
- package/src/__tests__/cli.smoke.test.ts +2 -2
- package/src/__tests__/global-setup.ts +2 -3
- package/src/__tests__/orchestrator-claim-secret.test.ts +111 -0
- package/src/__tests__/orchestrator-env-scrub.test.ts +160 -163
- package/src/__tests__/orchestrator-handle-contract.ts +134 -134
- package/src/__tests__/orchestrator-node-identity.test.ts +177 -203
- package/src/__tests__/orchestrator-ports.test.ts +124 -143
- package/src/__tests__/orchestrator-push.test.ts +138 -146
- package/src/__tests__/orchestrator.test.ts +1017 -1063
- package/src/__tests__/ui-access.test.ts +30 -0
- package/src/bin/host.ts +397 -572
- package/src/bin/join-output.ts +120 -0
- package/src/bin/nat-output.ts +188 -0
- package/src/bin/ui-access.ts +50 -0
- package/src/{donation → hosted}/__tests__/fake-orchestrator.test.ts +172 -173
- package/src/{donation → hosted}/__tests__/fake-orchestrator.ts +43 -23
- package/src/hosted/__tests__/hosted-node-service.test.ts +708 -0
- package/src/hosted/__tests__/hosted-node-supervisor.test.ts +475 -0
- package/src/hosted/__tests__/test-invitation.ts +33 -0
- package/src/hosted/claim-details.ts +103 -0
- package/src/hosted/hosted-node-service.ts +814 -0
- package/src/hosted/hosted-node-store.ts +144 -0
- package/src/hosted/hosted-node-supervisor.ts +439 -0
- package/src/hosted/hosted-node-watcher.ts +288 -0
- package/src/hosted/index.ts +53 -0
- package/src/hosted/node-status.ts +97 -0
- package/src/hosted/types.ts +160 -0
- package/src/index.ts +72 -91
- package/src/installer/__tests__/config.test.ts +15 -40
- package/src/installer/__tests__/installer.smoke.test.ts +184 -263
- package/src/installer/__tests__/wizard.test.ts +25 -13
- package/src/installer/config.ts +201 -175
- package/src/installer/index.ts +252 -327
- package/src/installer/paths.ts +104 -109
- package/src/installer/wizard.ts +24 -26
- package/src/nat/__tests__/address-resolver.test.ts +107 -82
- package/src/nat/__tests__/nat-service.test.ts +608 -515
- package/src/nat/__tests__/nat-store.test.ts +49 -12
- package/src/nat/__tests__/network-mode.test.ts +38 -0
- package/src/nat/__tests__/port-mapper.test.ts +30 -191
- package/src/nat/__tests__/reachability.test.ts +96 -13
- package/src/nat/address-resolver.ts +94 -52
- package/src/nat/address-watch.ts +92 -0
- package/src/nat/ddns/duckdns.ts +5 -1
- package/src/nat/ddns/index.ts +6 -0
- package/src/nat/index.ts +33 -13
- package/src/nat/nat-service.ts +942 -501
- package/src/nat/nat-store.ts +126 -31
- package/src/nat/network-mode.ts +36 -0
- package/src/nat/port-mapper.ts +241 -329
- package/src/nat/reachability.ts +155 -34
- package/src/nat/types.ts +110 -37
- package/src/{installer/__tests__/identity.test.ts → orchestrator/__tests__/identity-file.test.ts} +34 -34
- package/src/orchestrator/__tests__/node-identity.test.ts +62 -62
- package/src/orchestrator/host-process-orchestrator.ts +1089 -1260
- package/src/{installer/identity.ts → orchestrator/identity-file.ts} +56 -56
- package/src/orchestrator/index.ts +9 -10
- package/src/orchestrator/node-identity.ts +41 -41
- package/src/orchestrator/port-allocator.ts +71 -73
- package/src/orchestrator/state-store.ts +76 -90
- package/src/orchestrator/types.ts +34 -23
- package/src/package-version.ts +4 -0
- package/src/server/__tests__/bus.test.ts +38 -38
- package/src/server/__tests__/error-handler.test.ts +81 -118
- package/src/server/__tests__/fakes.ts +15 -18
- package/src/server/__tests__/hosted-nodes-route.test.ts +161 -0
- package/src/server/__tests__/nodes-route.test.ts +114 -283
- package/src/server/__tests__/publishers.test.ts +193 -180
- package/src/server/__tests__/server.smoke.test.ts +134 -223
- package/src/server/__tests__/settings-route.test.ts +210 -195
- package/src/server/__tests__/sse-route.test.ts +119 -119
- package/src/server/__tests__/status-route.test.ts +82 -121
- package/src/server/error-handler.ts +112 -178
- package/src/server/events/types.ts +20 -24
- package/src/server/index.ts +223 -267
- package/src/server/routes/hosted-nodes.ts +83 -0
- package/src/server/routes/nat.ts +75 -63
- package/src/server/routes/nodes.ts +96 -188
- package/src/server/routes/settings.ts +20 -15
- package/src/server/routes/status.ts +5 -67
- package/src/server/server.ts +8 -8
- package/src/server/settings-store.ts +2 -2
- package/src/server/static.ts +1 -2
- package/src/update/index.ts +2 -2
- package/src/update/store.ts +1 -1
- package/src/update/types.ts +1 -1
- package/dist/auth/duration.d.ts +0 -1
- package/dist/auth/duration.js +0 -32
- package/dist/auth/duration.js.map +0 -1
- package/dist/auth/index.d.ts +0 -11
- package/dist/auth/index.js +0 -9
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/self-label.d.ts +0 -36
- package/dist/auth/self-label.js +0 -57
- package/dist/auth/self-label.js.map +0 -1
- package/dist/auth/trust-circle-store.d.ts +0 -26
- package/dist/auth/trust-circle-store.js +0 -129
- package/dist/auth/trust-circle-store.js.map +0 -1
- package/dist/auth/trust-circle.d.ts +0 -156
- package/dist/auth/trust-circle.js +0 -307
- package/dist/auth/trust-circle.js.map +0 -1
- package/dist/auth/types.d.ts +0 -84
- package/dist/auth/types.js +0 -24
- package/dist/auth/types.js.map +0 -1
- package/dist/donation/donation-service.d.ts +0 -389
- package/dist/donation/donation-service.js +0 -828
- package/dist/donation/donation-service.js.map +0 -1
- package/dist/donation/donation-store.d.ts +0 -51
- package/dist/donation/donation-store.js +0 -152
- package/dist/donation/donation-store.js.map +0 -1
- package/dist/donation/donation-supervisor.js +0 -364
- package/dist/donation/donation-supervisor.js.map +0 -1
- package/dist/donation/grant-service.d.ts +0 -80
- package/dist/donation/grant-service.js +0 -210
- package/dist/donation/grant-service.js.map +0 -1
- package/dist/donation/grant-store.d.ts +0 -38
- package/dist/donation/grant-store.js +0 -135
- package/dist/donation/grant-store.js.map +0 -1
- package/dist/donation/index.d.ts +0 -20
- package/dist/donation/index.js +0 -17
- package/dist/donation/index.js.map +0 -1
- package/dist/donation/types.d.ts +0 -224
- package/dist/donation/types.js +0 -40
- package/dist/donation/types.js.map +0 -1
- package/dist/installer/identity.js.map +0 -1
- package/dist/owner/index.d.ts +0 -11
- package/dist/owner/index.js +0 -11
- package/dist/owner/index.js.map +0 -1
- package/dist/owner/owner-node-client.d.ts +0 -110
- package/dist/owner/owner-node-client.js +0 -184
- package/dist/owner/owner-node-client.js.map +0 -1
- package/dist/server/routes/bootstrap-node-validation.d.ts +0 -115
- package/dist/server/routes/bootstrap-node-validation.js +0 -197
- package/dist/server/routes/bootstrap-node-validation.js.map +0 -1
- package/dist/server/routes/grants-admin.d.ts +0 -29
- package/dist/server/routes/grants-admin.js +0 -58
- package/dist/server/routes/grants-admin.js.map +0 -1
- package/dist/server/routes/grants.d.ts +0 -28
- package/dist/server/routes/grants.js +0 -165
- package/dist/server/routes/grants.js.map +0 -1
- package/dist/server/routes/provision-request-validation.d.ts +0 -45
- package/dist/server/routes/provision-request-validation.js +0 -97
- package/dist/server/routes/provision-request-validation.js.map +0 -1
- package/dist/server/routes/strands.d.ts +0 -20
- package/dist/server/routes/strands.js +0 -38
- package/dist/server/routes/strands.js.map +0 -1
- package/dist/server/routes/trust-circle.d.ts +0 -17
- package/dist/server/routes/trust-circle.js +0 -35
- package/dist/server/routes/trust-circle.js.map +0 -1
- package/dist/strands/index.d.ts +0 -7
- package/dist/strands/index.js +0 -6
- package/dist/strands/index.js.map +0 -1
- package/dist/strands/strand-service.d.ts +0 -50
- package/dist/strands/strand-service.js +0 -103
- package/dist/strands/strand-service.js.map +0 -1
- package/dist/strands/types.d.ts +0 -93
- package/dist/strands/types.js +0 -23
- package/dist/strands/types.js.map +0 -1
- package/dist/ui/assets/index-C6nELNfC.js +0 -23
- package/dist/ui/assets/index-C6nELNfC.js.map +0 -1
- package/dist/ui/assets/index-TtIYSeZO.css +0 -1
- package/src/__tests__/cli-invite.smoke.test.ts +0 -192
- package/src/__tests__/host-owner.smoke.test.ts +0 -123
- package/src/__tests__/orchestrator-owner.test.ts +0 -234
- package/src/__tests__/orchestrator-pin-keys.test.ts +0 -152
- package/src/auth/__tests__/duration.test.ts +0 -28
- package/src/auth/__tests__/self-label.test.ts +0 -85
- package/src/auth/__tests__/trust-circle-integration.test.ts +0 -152
- package/src/auth/__tests__/trust-circle-store.test.ts +0 -115
- package/src/auth/__tests__/trust-circle.test.ts +0 -445
- package/src/auth/duration.ts +0 -33
- package/src/auth/index.ts +0 -21
- package/src/auth/self-label.ts +0 -74
- package/src/auth/trust-circle-store.ts +0 -155
- package/src/auth/trust-circle.ts +0 -395
- package/src/auth/types.ts +0 -99
- package/src/donation/__tests__/donation-service.test.ts +0 -1193
- package/src/donation/__tests__/donation-supervisor.test.ts +0 -548
- package/src/donation/__tests__/grant-service.test.ts +0 -213
- package/src/donation/__tests__/grant-store.test.ts +0 -113
- package/src/donation/donation-service.ts +0 -1033
- package/src/donation/donation-store.ts +0 -176
- package/src/donation/donation-supervisor.ts +0 -411
- package/src/donation/grant-service.ts +0 -252
- package/src/donation/grant-store.ts +0 -152
- package/src/donation/index.ts +0 -65
- package/src/donation/types.ts +0 -260
- package/src/owner/__tests__/owner-node-client.test.ts +0 -194
- package/src/owner/index.ts +0 -12
- package/src/owner/owner-node-client.ts +0 -259
- package/src/server/__tests__/bootstrap-node-validation.test.ts +0 -138
- package/src/server/__tests__/grants-admin-route.test.ts +0 -171
- package/src/server/__tests__/grants-route.test.ts +0 -394
- package/src/server/__tests__/strands-route.test.ts +0 -234
- package/src/server/routes/bootstrap-node-validation.ts +0 -206
- package/src/server/routes/grants-admin.ts +0 -74
- package/src/server/routes/grants.ts +0 -193
- package/src/server/routes/provision-request-validation.ts +0 -105
- package/src/server/routes/strands.ts +0 -54
- package/src/server/routes/trust-circle.ts +0 -49
- package/src/strands/__tests__/strand-service.test.ts +0 -165
- package/src/strands/index.ts +0 -14
- package/src/strands/strand-service.ts +0 -135
- package/src/strands/types.ts +0 -102
|
@@ -1,125 +1,187 @@
|
|
|
1
|
-
import { type DdnsProviderInfo, type NatHandlers, type NatSettingsFile, type NatStatusSnapshot } from './types.js';
|
|
1
|
+
import { type DdnsProviderInfo, type ManualForwardPatch, type NatHandlers, type NatSettingsFile, type NatStatusSnapshot } from './types.js';
|
|
2
2
|
import { NatStore } from './nat-store.js';
|
|
3
3
|
import { ExternalIpDetector } from './external-ip.js';
|
|
4
4
|
import { type PortMapper } from './port-mapper.js';
|
|
5
5
|
import { type SecretsStore } from './secrets/index.js';
|
|
6
|
+
import { type NodeAddressesStaleListener } from './address-watch.js';
|
|
7
|
+
import type { ManagedNodeInfo, NodeStateListener } from '../orchestrator/types.js';
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
* How long a node may sit `stopped` before its mappings are released. Longer
|
|
10
|
+
* than the hosted-node supervisor's whole respawn backoff (150 s), so a crash
|
|
11
|
+
* followed by a respawn keeps its mapping.
|
|
12
|
+
*/
|
|
13
|
+
export declare const NAT_UNMAP_GRACE_MS: number;
|
|
14
|
+
/** The backstop reconcile cadence; state-change events trigger passes between ticks. */
|
|
15
|
+
export declare const NAT_RECONCILE_INTERVAL_MS = 60000;
|
|
16
|
+
/**
|
|
17
|
+
* How often the external IP is re-detected, and how often gateway discovery is
|
|
18
|
+
* retried while UPnP is on and no router has answered.
|
|
14
19
|
*/
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
export declare const NAT_IP_REDETECT_INTERVAL_MS: number;
|
|
21
|
+
/**
|
|
22
|
+
* The orchestrator surface the service needs: the node list and cadre-host's
|
|
23
|
+
* own state-change subscription. `HostProcessOrchestrator` satisfies this; the
|
|
24
|
+
* hosted-node supervisor declares the same slice.
|
|
25
|
+
*/
|
|
26
|
+
export interface NatNodeSource {
|
|
27
|
+
listNodes(): ManagedNodeInfo[];
|
|
28
|
+
onStateChange(listener: NodeStateListener): () => void;
|
|
20
29
|
}
|
|
21
|
-
/** Listener notified when the
|
|
22
|
-
export type
|
|
30
|
+
/** Listener notified when the status snapshot changed in a way the UI should follow. */
|
|
31
|
+
export type NatChangeListener = (snapshot: NatStatusSnapshot) => void;
|
|
23
32
|
export interface NatServiceOptions {
|
|
24
|
-
/** Cadre-host root directory (same one orchestrator
|
|
33
|
+
/** Cadre-host root directory (same one the orchestrator and the hosted-node store use). */
|
|
25
34
|
rootDir: string;
|
|
26
|
-
/**
|
|
27
|
-
|
|
35
|
+
/** Where the hosted nodes and their ports come from. */
|
|
36
|
+
nodeSource: NatNodeSource;
|
|
28
37
|
/** Clock override for tests. */
|
|
29
38
|
now?: () => Date;
|
|
30
39
|
/** Fetch override for tests. */
|
|
31
40
|
fetch?: typeof fetch;
|
|
32
41
|
/** Test-only: stub the keytar/file-store. Default: createSecretsStore. */
|
|
33
42
|
secretsStore?: SecretsStore;
|
|
34
|
-
/** Test-only: stub the
|
|
43
|
+
/** Test-only: stub the router. Default: `UpnpPortMapper`. */
|
|
35
44
|
portMapper?: PortMapper;
|
|
36
45
|
/** Test-only: stub the external-IP detector. */
|
|
37
46
|
externalIpDetector?: ExternalIpDetector;
|
|
38
47
|
/** Optional: re-use an existing NatStore (mostly for tests). */
|
|
39
48
|
store?: NatStore;
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
|
|
49
|
+
/** Lease TTL asked of the router. Default 1 h. */
|
|
50
|
+
leaseTtlMs?: number;
|
|
51
|
+
/** Test-only: stub the interface read behind `network: auto`. Default: `publicInterfaceAddress()`. */
|
|
52
|
+
publicInterfaceAddress?: () => string | null;
|
|
44
53
|
}
|
|
45
54
|
/**
|
|
46
|
-
* NatService —
|
|
47
|
-
* and
|
|
55
|
+
* NatService — one mapping table for every node the host runs, keyed by node
|
|
56
|
+
* id, with a route per port (TCP and WebSocket); external-IP detection; DDNS;
|
|
57
|
+
* and the public addresses a node announces.
|
|
48
58
|
*
|
|
49
59
|
* Lifecycle:
|
|
50
|
-
* - `start()`: load settings,
|
|
51
|
-
* external IP,
|
|
52
|
-
* - `stop()`:
|
|
53
|
-
* - `getStatus()`:
|
|
54
|
-
* - `
|
|
55
|
-
*
|
|
60
|
+
* - `start()`: load settings, discover the router (bounded), detect the
|
|
61
|
+
* external IP, start DDNS, then map the running nodes in the background.
|
|
62
|
+
* - `stop()`: clear timers only — mappings outlive the host process.
|
|
63
|
+
* - `getStatus()`: snapshot from cached state (cheap).
|
|
64
|
+
* - `publicAddressesFor(nodeId, ports)`: a node's public multiaddrs, also
|
|
65
|
+
* from cached state, predicting the identity mapping for a port that has
|
|
66
|
+
* no route yet.
|
|
67
|
+
* - `onNodeAddressesStale(listener)`: asked to restart a running node whose
|
|
68
|
+
* announced addresses no longer match `publicAddressesFor`, checked after
|
|
69
|
+
* every pass and every settings write (see `AddressWatch`).
|
|
70
|
+
*
|
|
71
|
+
* One reconcile pass against the node source behind three triggers (start,
|
|
72
|
+
* node state change, a 1-minute timer), plus one renewal pass for every lease
|
|
73
|
+
* every `DEFAULT_REFRESH_MS`. Passes are serialized on one promise tail, so a
|
|
74
|
+
* state change during a timer pass can neither map a port twice nor unmap a
|
|
75
|
+
* port the other pass is mapping.
|
|
56
76
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
77
|
+
* NOTE: this file holds the settings/DDNS glue, the mapping table and the status
|
|
78
|
+
* assembly together (about 890 lines; the stale-address check lives in
|
|
79
|
+
* `address-watch.ts` for that reason); when the next capability lands here, move
|
|
80
|
+
* the mapping table (`NodeEntry` through `releaseUpnpRoutes`) into its own module.
|
|
59
81
|
*/
|
|
60
82
|
export declare class NatService {
|
|
61
|
-
private readonly
|
|
83
|
+
private readonly nodeSource;
|
|
62
84
|
private readonly store;
|
|
63
85
|
private readonly nowFn;
|
|
64
86
|
private readonly fetchImpl;
|
|
87
|
+
private readonly portMapper;
|
|
88
|
+
private readonly leaseTtlMs;
|
|
89
|
+
private readonly secretsRootDir;
|
|
65
90
|
private secretsStore;
|
|
66
|
-
|
|
67
|
-
/** Caller-supplied detector — used as-is when present (skips the auto router-probe stitch). */
|
|
91
|
+
/** Caller-supplied detector — used as-is when present (skips the router-probe stitch). */
|
|
68
92
|
private readonly injectedDetector;
|
|
69
|
-
private
|
|
93
|
+
private detector;
|
|
70
94
|
private ddnsUpdater;
|
|
71
95
|
private currentSettings;
|
|
96
|
+
private gateway;
|
|
97
|
+
/** The public IPv4 an interface holds (`publicInterfaceAddress`), re-read at start and on every probe. */
|
|
98
|
+
private publicInterfaceIp;
|
|
99
|
+
private readonly readInterfaces;
|
|
72
100
|
private latestIp;
|
|
73
101
|
private lastTestedAt;
|
|
102
|
+
private readonly table;
|
|
74
103
|
private started;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
private
|
|
78
|
-
private
|
|
79
|
-
private
|
|
104
|
+
private tail;
|
|
105
|
+
/** True while an event-triggered pass is queued and not yet started (crash storms coalesce into it). */
|
|
106
|
+
private eventPassQueued;
|
|
107
|
+
private timers;
|
|
108
|
+
private unsubscribe;
|
|
109
|
+
private readonly changeListeners;
|
|
110
|
+
private lastSignature;
|
|
111
|
+
private readonly addressWatch;
|
|
80
112
|
constructor(opts: NatServiceOptions);
|
|
81
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Discover the router and detect the external IP (both awaited, both
|
|
115
|
+
* bounded), start DDNS, then map re-attached running nodes in the background
|
|
116
|
+
* so the management API comes up promptly. Idempotent.
|
|
117
|
+
*/
|
|
82
118
|
start(): Promise<void>;
|
|
83
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* Clear timers and release client resources. Idempotent.
|
|
121
|
+
*
|
|
122
|
+
* NOTE: deliberately unmaps nothing. Hosted children are detached and keep
|
|
123
|
+
* running across a host restart (an update restart included), so their
|
|
124
|
+
* mappings must outlive this process; they expire on their own within the
|
|
125
|
+
* lease TTL if the host stays down, and the next `start()` re-maps the
|
|
126
|
+
* re-attached nodes (re-mapping the same internal port is idempotent on the
|
|
127
|
+
* router).
|
|
128
|
+
*/
|
|
84
129
|
stop(): Promise<void>;
|
|
85
130
|
/** Cheap read of the current snapshot. */
|
|
86
131
|
getStatus(): NatStatusSnapshot;
|
|
87
|
-
/**
|
|
88
|
-
|
|
132
|
+
/** Current settings (cheap read; for handlers to surface to UI). */
|
|
133
|
+
getSettings(): NatSettingsFile;
|
|
134
|
+
/**
|
|
135
|
+
* The public multiaddrs for a node, from cached state. A port with no route
|
|
136
|
+
* yet is predicted to land on the identity mapping when UPnP is enabled and
|
|
137
|
+
* a gateway was discovered — callers ask at spawn time, before the mapping
|
|
138
|
+
* for a brand-new node exists. A port whose mapping attempt failed is not
|
|
139
|
+
* predicted.
|
|
140
|
+
*/
|
|
141
|
+
publicAddressesFor(nodeId: string, ports: {
|
|
142
|
+
p2p: number;
|
|
143
|
+
ws?: number;
|
|
144
|
+
}): string[];
|
|
89
145
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
146
|
+
* Register a listener fired whenever a node's routes, the gateway, the
|
|
147
|
+
* external IP, the CGNAT flag, the UPnP toggle or the DDNS settings change.
|
|
148
|
+
* Returns an unsubscribe fn.
|
|
93
149
|
*/
|
|
94
|
-
|
|
150
|
+
onChange(listener: NatChangeListener): () => void;
|
|
95
151
|
/**
|
|
96
|
-
* Register a listener
|
|
97
|
-
* (
|
|
98
|
-
*
|
|
99
|
-
* unsubscribe fn.
|
|
152
|
+
* Register a listener asked to restart a running node whose announced addresses
|
|
153
|
+
* (`ManagedNodeInfo.announcedAddrs`) differ from `publicAddressesFor` — at most
|
|
154
|
+
* once per node per `NAT_ADDRESS_RESTART_MIN_INTERVAL_MS`. Returns an unsubscribe fn.
|
|
100
155
|
*/
|
|
101
|
-
|
|
156
|
+
onNodeAddressesStale(listener: NodeAddressesStaleListener): () => void;
|
|
157
|
+
/** List available DDNS providers (UI listing for configuration). */
|
|
158
|
+
listDdnsProviders(): DdnsProviderInfo[];
|
|
102
159
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
160
|
+
* One reconcile pass against the node source: map running nodes, release
|
|
161
|
+
* nodes stopped past the grace, forget terminated ones. Serialized against
|
|
162
|
+
* every other pass, so a caller may get a queued pass rather than an
|
|
163
|
+
* immediate one.
|
|
106
164
|
*/
|
|
107
|
-
|
|
108
|
-
/** Deliver an address set to every registered listener (errors are logged, not thrown). */
|
|
109
|
-
private notifyAddressListeners;
|
|
165
|
+
reconcile(): Promise<void>;
|
|
110
166
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* or the bounded budget elapses (best-effort thereafter). Awaited by start() so
|
|
116
|
-
* the management API — the invite-minting path — does not come up first.
|
|
167
|
+
* One renewal pass: re-request every UPnP-eligible mapping of every running
|
|
168
|
+
* node, failed ones included. Each renewal is isolated; one failure does not
|
|
169
|
+
* stop the pass. A router that answers with another external port updates
|
|
170
|
+
* the route.
|
|
117
171
|
*/
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
|
|
172
|
+
renewMappings(): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* The 5-minute probe pass: re-read the interfaces and re-route every node when
|
|
175
|
+
* the mode `auto` lands on changes; while UPnP is in use and no router has
|
|
176
|
+
* answered, search again and map the running nodes as soon as one does — a
|
|
177
|
+
* host that boots before its network, or a router that comes up later, is
|
|
178
|
+
* found here rather than at the next restart; then re-detect the external IP.
|
|
179
|
+
*/
|
|
180
|
+
redetect(): Promise<void>;
|
|
181
|
+
/** Re-discover the router if needed, re-map everything, re-detect the IP, then return a fresh snapshot. */
|
|
182
|
+
testReachability(): Promise<NatStatusSnapshot>;
|
|
121
183
|
/** Replace settings; persists to disk and reconfigures the runtime. */
|
|
122
|
-
putSettings(patch: Partial<Omit<NatSettingsFile, 'version'>>): Promise<NatStatusSnapshot>;
|
|
184
|
+
putSettings(patch: Partial<Omit<NatSettingsFile, 'version' | 'forwards'>>): Promise<NatStatusSnapshot>;
|
|
123
185
|
/**
|
|
124
186
|
* Set DDNS configuration and persist secret values into the SecretsStore.
|
|
125
187
|
* Throws if the provider is unknown or required secrets are missing.
|
|
@@ -130,14 +192,95 @@ export declare class NatService {
|
|
|
130
192
|
config: Record<string, string>;
|
|
131
193
|
externallyManaged?: boolean;
|
|
132
194
|
}): Promise<NatStatusSnapshot>;
|
|
133
|
-
/**
|
|
134
|
-
|
|
135
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Record the external ports the user forwarded by hand for one node (`null`
|
|
197
|
+
* clears a port). A port that became manual releases its UPnP mapping; a
|
|
198
|
+
* port whose entry was cleared is re-requested over UPnP.
|
|
199
|
+
*/
|
|
200
|
+
putForward(nodeId: string, patch: ManualForwardPatch): Promise<NatStatusSnapshot>;
|
|
201
|
+
private enqueue;
|
|
202
|
+
/** Fire-and-forget pass for the timer / event / startup triggers. */
|
|
203
|
+
private sweep;
|
|
204
|
+
/**
|
|
205
|
+
* One pass per burst of events: an event while a pass is queued joins it,
|
|
206
|
+
* and an event during a running pass queues exactly one more, so a node that
|
|
207
|
+
* spawned after the running pass listed the nodes is mapped by the next pass
|
|
208
|
+
* rather than by the timer.
|
|
209
|
+
*/
|
|
210
|
+
private queueEventPass;
|
|
211
|
+
private reconcileOnce;
|
|
212
|
+
/**
|
|
213
|
+
* A node no longer listed was terminated (`removeContainer`): release its
|
|
214
|
+
* mappings at once and drop its manual forward. A forward left behind for a
|
|
215
|
+
* node that vanished while the host was down goes the same way.
|
|
216
|
+
*/
|
|
217
|
+
private forgetMissingNodes;
|
|
218
|
+
private reconcileNode;
|
|
219
|
+
/**
|
|
220
|
+
* Bring one node's routes in line with the settings: manual wins over UPnP;
|
|
221
|
+
* UPnP off releases every `upnp` route; with `mapMissing`, a port with no
|
|
222
|
+
* route and no recorded failure (or an expired lease) is requested.
|
|
223
|
+
*/
|
|
224
|
+
private reconcileRoutes;
|
|
225
|
+
private renewOnce;
|
|
226
|
+
/**
|
|
227
|
+
* Ask the router for one port. A refusal records `error` on that port only.
|
|
228
|
+
*
|
|
229
|
+
* NOTE: a router that stops answering costs each attempt its 10 s timeout, so a
|
|
230
|
+
* pass over N mapped ports can take 10 s × N; passes are serialized, so they queue
|
|
231
|
+
* rather than overlap. If that ever shows, skip ports whose last failure was a
|
|
232
|
+
* timeout until the next renewal pass.
|
|
233
|
+
*/
|
|
234
|
+
private mapRoute;
|
|
235
|
+
private unmapRoute;
|
|
236
|
+
private releaseUpnpRoutes;
|
|
237
|
+
private kindsOf;
|
|
238
|
+
private leaseExpired;
|
|
239
|
+
/** A UPnP route whose lease ran out reads as no route, keeping any recorded failure. */
|
|
240
|
+
private effectiveRoute;
|
|
241
|
+
private discoverGateway;
|
|
242
|
+
/**
|
|
243
|
+
* Detect the external IP. A detection that finds nothing (or throws), or that
|
|
244
|
+
* lost the public echo the previous one had, keeps the previous result: one
|
|
245
|
+
* failed probe must not drop every node's public address, and a router-only
|
|
246
|
+
* answer must not flip the CGNAT flag the two probes had agreed on.
|
|
247
|
+
*/
|
|
136
248
|
private detectIp;
|
|
137
|
-
private
|
|
249
|
+
private knowsLessThanPrevious;
|
|
250
|
+
private ipDetector;
|
|
251
|
+
/** The detected external IP for display and DDNS: the public probe's, else the router's. */
|
|
252
|
+
private detectedIp;
|
|
253
|
+
/** The IP used in `/ip4/` addresses: only a public IPv4 counts. Public mode prefers the interface's own. */
|
|
254
|
+
private publicIpv4;
|
|
255
|
+
/**
|
|
256
|
+
* Re-read the interfaces (a VPS gains an address, a laptop moves networks); true when that
|
|
257
|
+
* changed the mode in effect, so the caller re-routes every node in the same pass.
|
|
258
|
+
*/
|
|
259
|
+
private refreshNetworkMode;
|
|
260
|
+
/** The mode in effect: the `network` setting, or what `auto` reads from the interfaces. */
|
|
261
|
+
private networkMode;
|
|
262
|
+
/** UPnP is asked for nothing in public mode: there is no router to ask. */
|
|
263
|
+
private usesUpnp;
|
|
264
|
+
/** An interface holding the public address rules out carrier-grade NAT, whatever the probes say. */
|
|
265
|
+
private cgnatDetected;
|
|
266
|
+
private describeNode;
|
|
267
|
+
private hostKnown;
|
|
268
|
+
private addressesFor;
|
|
269
|
+
private routeOrPrediction;
|
|
270
|
+
private ddnsStatus;
|
|
271
|
+
/**
|
|
272
|
+
* The end of every pass and every settings write: tell the change listeners
|
|
273
|
+
* when the snapshot moved, then ask for a restart of every running node whose
|
|
274
|
+
* announced addresses went stale. Running the check here rather than only on a
|
|
275
|
+
* change is what lets a difference deferred by the restart rate limit fire on the
|
|
276
|
+
* first timer pass after the limit ends.
|
|
277
|
+
*/
|
|
278
|
+
private publish;
|
|
279
|
+
/** Fire the change listeners when the snapshot differs (timestamps aside) from the last one they saw. */
|
|
280
|
+
private notifyIfChanged;
|
|
138
281
|
}
|
|
139
282
|
/**
|
|
140
|
-
* Wrap a NatService into the typed handler shape consumed by
|
|
141
|
-
*
|
|
283
|
+
* Wrap a NatService into the typed handler shape consumed by the local UI
|
|
284
|
+
* server. Same shape as `createUpdateHandlers`.
|
|
142
285
|
*/
|
|
143
286
|
export declare function createNatHandlers(service: NatService): NatHandlers;
|