@serfab/cadre-host 1.13.0 → 1.14.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 +332 -423
- package/dist/bin/host.d.ts +6 -3
- package/dist/bin/host.js +301 -505
- 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 +49 -0
- package/dist/bin/nat-output.js +127 -0
- package/dist/bin/nat-output.js.map +1 -0
- package/dist/hosted/claim-details.d.ts +44 -0
- package/dist/hosted/claim-details.js +66 -0
- package/dist/hosted/claim-details.js.map +1 -0
- package/dist/hosted/hosted-node-service.d.ts +318 -0
- package/dist/hosted/hosted-node-service.js +666 -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 +83 -0
- package/dist/hosted/hosted-node-watcher.js +224 -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 +35 -0
- package/dist/hosted/node-status.js +61 -0
- package/dist/hosted/node-status.js.map +1 -0
- package/dist/hosted/types.d.ts +134 -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 +4 -34
- package/dist/installer/config.js +3 -18
- package/dist/installer/config.js.map +1 -1
- package/dist/installer/index.d.ts +7 -19
- package/dist/installer/index.js +14 -69
- 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 +0 -7
- package/dist/installer/wizard.js +1 -8
- 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 +12 -9
- package/dist/nat/index.js +6 -5
- package/dist/nat/index.js.map +1 -1
- package/dist/nat/nat-service.d.ts +203 -77
- package/dist/nat/nat-service.js +602 -237
- package/dist/nat/nat-service.js.map +1 -1
- package/dist/nat/nat-store.d.ts +12 -5
- package/dist/nat/nat-store.js +114 -30
- package/dist/nat/nat-store.js.map +1 -1
- 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 +31 -15
- package/dist/nat/reachability.js +97 -22
- package/dist/nat/reachability.js.map +1 -1
- package/dist/nat/types.d.ts +78 -27
- package/dist/nat/types.js +8 -5
- package/dist/nat/types.js.map +1 -1
- package/dist/orchestrator/host-process-orchestrator.d.ts +29 -71
- package/dist/orchestrator/host-process-orchestrator.js +78 -218
- 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/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 +2 -7
- package/dist/server/routes/settings.js +3 -7
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/status.d.ts +2 -25
- package/dist/server/routes/status.js +1 -11
- 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-4FWuU8ye.js +19 -0
- package/dist/ui/assets/index-4FWuU8ye.js.map +1 -0
- package/dist/ui/assets/index-Di9Q4d01.css +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 -6
- package/src/__tests__/cli-nat.smoke.test.ts +219 -212
- package/src/__tests__/cli.smoke.test.ts +1 -1
- package/src/__tests__/global-setup.ts +2 -3
- package/src/__tests__/orchestrator-claim-secret.test.ts +112 -0
- package/src/__tests__/orchestrator-handle-contract.ts +134 -134
- package/src/__tests__/orchestrator-node-identity.test.ts +182 -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 +1019 -1063
- package/src/bin/host.ts +368 -553
- package/src/bin/join-output.ts +120 -0
- package/src/bin/nat-output.ts +177 -0
- package/src/{donation → hosted}/__tests__/fake-orchestrator.test.ts +173 -173
- package/src/{donation → hosted}/__tests__/fake-orchestrator.ts +265 -243
- package/src/hosted/__tests__/hosted-node-service.test.ts +609 -0
- package/src/hosted/__tests__/hosted-node-supervisor.test.ts +474 -0
- package/src/hosted/__tests__/test-invitation.ts +33 -0
- package/src/hosted/claim-details.ts +96 -0
- package/src/hosted/hosted-node-service.ts +795 -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 +250 -0
- package/src/hosted/index.ts +53 -0
- package/src/hosted/node-status.ts +71 -0
- package/src/hosted/types.ts +153 -0
- package/src/index.ts +72 -91
- package/src/installer/__tests__/config.test.ts +15 -40
- package/src/installer/__tests__/installer.smoke.test.ts +5 -86
- package/src/installer/__tests__/wizard.test.ts +56 -64
- package/src/installer/config.ts +135 -175
- package/src/installer/index.ts +15 -83
- package/src/installer/paths.ts +104 -109
- package/src/installer/wizard.ts +87 -103
- package/src/nat/__tests__/address-resolver.test.ts +107 -82
- package/src/nat/__tests__/nat-service.test.ts +433 -408
- package/src/nat/__tests__/nat-store.test.ts +127 -93
- 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 +87 -71
- package/src/nat/nat-service.ts +889 -501
- package/src/nat/nat-store.ts +237 -154
- package/src/nat/port-mapper.ts +241 -329
- package/src/nat/reachability.ts +134 -25
- package/src/nat/types.ts +209 -159
- 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 +81 -243
- 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/server/__tests__/bus.test.ts +38 -38
- package/src/server/__tests__/error-handler.test.ts +81 -118
- package/src/server/__tests__/fakes.ts +40 -44
- package/src/server/__tests__/hosted-nodes-route.test.ts +160 -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 +179 -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 +115 -123
- package/src/server/routes/status.ts +102 -134
- 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
package/dist/nat/types.d.ts
CHANGED
|
@@ -1,37 +1,80 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NAT/DDNS types for cadre-host.
|
|
3
3
|
*
|
|
4
|
-
* cadre-host runs on home/SMB machines that are typically behind NAT.
|
|
5
|
-
* dialable from the open internet the host must:
|
|
6
|
-
* 1.
|
|
4
|
+
* cadre-host runs on home/SMB machines that are typically behind NAT. For the
|
|
5
|
+
* nodes it runs to be dialable from the open internet the host must:
|
|
6
|
+
* 1. Map every hosted node's two libp2p ports (TCP, and the WebSocket port a
|
|
7
|
+
* phone dials) through the upstream router, or let the user forward them
|
|
8
|
+
* by hand.
|
|
7
9
|
* 2. Detect its external IP (and whether it's behind CGNAT).
|
|
8
10
|
* 3. Optionally publish a stable hostname via dynamic DNS.
|
|
9
11
|
*
|
|
10
|
-
* State for these
|
|
11
|
-
*
|
|
12
|
+
* State for these concerns lives in `<rootDir>/nat.json` (user settings) and is
|
|
13
|
+
* exposed as a single `NatStatusSnapshot` to the management UI, with one
|
|
14
|
+
* `NodeReachability` entry per hosted node.
|
|
12
15
|
*
|
|
13
16
|
* Credentials for DDNS providers are NOT stored in `nat.json`. They go through
|
|
14
17
|
* the SecretsStore (keytar, with a 0600 file fallback).
|
|
15
18
|
*/
|
|
16
|
-
/**
|
|
17
|
-
export type PortForwardMode = 'auto-upnp' | 'auto-natpmp' | 'manual' | 'failed' | 'disabled';
|
|
18
|
-
/** Reachability verdict — best-effort heuristic until AutoNAT lands. */
|
|
19
|
+
/** Reachability roll-up across the host's running nodes — see `reachability.ts`. */
|
|
19
20
|
export type DirectReachability = 'reachable' | 'unreachable' | 'unknown' | 'cgnat';
|
|
20
|
-
/**
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/** The two ports of a hosted node that are mapped: libp2p TCP and libp2p WebSocket. */
|
|
22
|
+
export type PortKind = 'tcp' | 'ws';
|
|
23
|
+
/** Where a port's external route came from. */
|
|
24
|
+
export type PortRouteSource = 'upnp' | 'manual';
|
|
25
|
+
/** How one of a node's ports is reached from outside the home network. */
|
|
26
|
+
export interface PortRoute {
|
|
24
27
|
internalPort: number;
|
|
25
|
-
/**
|
|
28
|
+
/** Port reachable from outside; null when there is no route. */
|
|
29
|
+
externalPort: number | null;
|
|
30
|
+
source: PortRouteSource | null;
|
|
31
|
+
/** ISO timestamp when the router lease expires; UPnP routes only. */
|
|
32
|
+
leaseExpiresAt: string | null;
|
|
33
|
+
/** Last mapping failure, in plain language; null when the last attempt succeeded. */
|
|
34
|
+
error: string | null;
|
|
35
|
+
}
|
|
36
|
+
/** Per-node verdict. */
|
|
37
|
+
export type NodeVerdict = 'mapped' | 'manual' | 'unreachable';
|
|
38
|
+
/** Reachability of one hosted node, as reported in the status snapshot. */
|
|
39
|
+
export interface NodeReachability {
|
|
40
|
+
nodeId: string;
|
|
41
|
+
/** Whether the node's process is running; a stopped node keeps its last routes until the unmap grace elapses. */
|
|
42
|
+
running: boolean;
|
|
43
|
+
verdict: NodeVerdict;
|
|
44
|
+
/**
|
|
45
|
+
* Plain-language reason and remedy when unreachable, e.g. "Router refused
|
|
46
|
+
* the WebSocket port mapping. Forward port 10004 to 192.168.1.20 on your
|
|
47
|
+
* router, then tell cadre-host the external port."
|
|
48
|
+
*/
|
|
49
|
+
reason: string | null;
|
|
50
|
+
tcp: PortRoute;
|
|
51
|
+
/** Null for a handle persisted by an older build without a WebSocket port. */
|
|
52
|
+
ws: PortRoute | null;
|
|
53
|
+
/** Multiaddrs (no `/p2p/` suffix) through which the node is reachable from outside. */
|
|
54
|
+
publicAddrs: string[];
|
|
55
|
+
}
|
|
56
|
+
/** The UPnP gateway as the host last saw it. */
|
|
57
|
+
export interface NatGatewayStatus {
|
|
58
|
+
found: boolean;
|
|
59
|
+
/** This machine's address on the router's subnet — the address a user forwards to. */
|
|
60
|
+
lanAddress: string | null;
|
|
61
|
+
/** The WAN address the router reports for itself. */
|
|
26
62
|
routerExternalIp: string | null;
|
|
27
|
-
/**
|
|
28
|
-
|
|
63
|
+
/** Why discovery or the last gateway operation failed; null when it did not. */
|
|
64
|
+
lastError: string | null;
|
|
65
|
+
}
|
|
66
|
+
/** Snapshot returned to the management UI / CLI. */
|
|
67
|
+
export interface NatStatusSnapshot {
|
|
68
|
+
upnpEnabled: boolean;
|
|
69
|
+
gateway: NatGatewayStatus;
|
|
29
70
|
externalIp: string | null;
|
|
30
71
|
externalIpDetectedAt: string | null;
|
|
31
72
|
cgnatDetected: boolean;
|
|
73
|
+
/** Roll-up across running nodes; see `reachability.ts`. */
|
|
32
74
|
directReachability: DirectReachability;
|
|
33
75
|
lastTestedAt: string | null;
|
|
34
76
|
ddns: NatDdnsStatus;
|
|
77
|
+
nodes: NodeReachability[];
|
|
35
78
|
}
|
|
36
79
|
/** DDNS sub-section of the status snapshot. */
|
|
37
80
|
export interface NatDdnsStatus {
|
|
@@ -48,18 +91,26 @@ export interface NatDdnsStatus {
|
|
|
48
91
|
/** Most recent error message, null when last attempt succeeded. */
|
|
49
92
|
lastError: string | null;
|
|
50
93
|
}
|
|
94
|
+
/** The external ports a user forwarded on their router for one node, per port kind. */
|
|
95
|
+
export interface ManualForward {
|
|
96
|
+
tcp?: number;
|
|
97
|
+
ws?: number;
|
|
98
|
+
}
|
|
99
|
+
/** Patch applied by `PUT /nat/nodes/:nodeId/forward`: `null` clears that port. */
|
|
100
|
+
export interface ManualForwardPatch {
|
|
101
|
+
tcp?: number | null;
|
|
102
|
+
ws?: number | null;
|
|
103
|
+
}
|
|
51
104
|
/**
|
|
52
105
|
* On-disk shape of `nat.json`. NEVER contains DDNS credentials — those live
|
|
53
106
|
* in the SecretsStore.
|
|
54
107
|
*/
|
|
55
108
|
export interface NatSettingsFile {
|
|
56
109
|
version: 1;
|
|
57
|
-
/**
|
|
58
|
-
externalPort: number;
|
|
59
|
-
/** Internal libp2p port. Default 4001. */
|
|
60
|
-
internalPort: number;
|
|
61
|
-
/** Whether to attempt UPnP/NAT-PMP at all. */
|
|
110
|
+
/** Whether to ask the router for port mappings at all. */
|
|
62
111
|
upnpEnabled: boolean;
|
|
112
|
+
/** Per node id: the external port the user forwarded on their router, per port kind. */
|
|
113
|
+
forwards: Record<string, ManualForward>;
|
|
63
114
|
ddns: NatDdnsSettings;
|
|
64
115
|
}
|
|
65
116
|
/** DDNS sub-section of `nat.json`. */
|
|
@@ -79,8 +130,8 @@ export interface NatDdnsSettings {
|
|
|
79
130
|
}
|
|
80
131
|
/** Typed error codes for NatError. */
|
|
81
132
|
export type NatErrorCode = 'mapping_failed' | 'router_unreachable' | 'ip_detection_failed' | 'ddns_provider_unknown' | 'ddns_credentials_missing' | 'ddns_update_failed' | 'secrets_unavailable' | 'storage_error' | 'invalid_config'
|
|
82
|
-
/**
|
|
83
|
-
| '
|
|
133
|
+
/** A manual forward named a node id the host does not run. */
|
|
134
|
+
| 'unknown_node';
|
|
84
135
|
/** Typed error carrying a stable `code` for HTTP mapping in the local-ui. */
|
|
85
136
|
export declare class NatError extends Error {
|
|
86
137
|
readonly code: NatErrorCode;
|
|
@@ -102,11 +153,10 @@ export interface DdnsProviderInfo {
|
|
|
102
153
|
configFields: ReadonlyArray<DdnsConfigField>;
|
|
103
154
|
}
|
|
104
155
|
/**
|
|
105
|
-
* Typed HTTP handlers exposed to
|
|
156
|
+
* Typed HTTP handlers exposed to the local UI server for Fastify wiring.
|
|
106
157
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* status code.
|
|
158
|
+
* These take typed objects and either return typed results or throw a
|
|
159
|
+
* `NatError` whose `.code` the error handler maps to an HTTP status code.
|
|
110
160
|
*/
|
|
111
161
|
export interface NatHandlers {
|
|
112
162
|
getStatus(): Promise<NatStatusSnapshot>;
|
|
@@ -118,5 +168,6 @@ export interface NatHandlers {
|
|
|
118
168
|
config: Record<string, string>;
|
|
119
169
|
externallyManaged?: boolean;
|
|
120
170
|
}): Promise<NatStatusSnapshot>;
|
|
121
|
-
putSettings(body: Partial<Omit<NatSettingsFile, 'version'>>): Promise<NatStatusSnapshot>;
|
|
171
|
+
putSettings(body: Partial<Omit<NatSettingsFile, 'version' | 'forwards'>>): Promise<NatStatusSnapshot>;
|
|
172
|
+
putForward(nodeId: string, patch: ManualForwardPatch): Promise<NatStatusSnapshot>;
|
|
122
173
|
}
|
package/dist/nat/types.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NAT/DDNS types for cadre-host.
|
|
3
3
|
*
|
|
4
|
-
* cadre-host runs on home/SMB machines that are typically behind NAT.
|
|
5
|
-
* dialable from the open internet the host must:
|
|
6
|
-
* 1.
|
|
4
|
+
* cadre-host runs on home/SMB machines that are typically behind NAT. For the
|
|
5
|
+
* nodes it runs to be dialable from the open internet the host must:
|
|
6
|
+
* 1. Map every hosted node's two libp2p ports (TCP, and the WebSocket port a
|
|
7
|
+
* phone dials) through the upstream router, or let the user forward them
|
|
8
|
+
* by hand.
|
|
7
9
|
* 2. Detect its external IP (and whether it's behind CGNAT).
|
|
8
10
|
* 3. Optionally publish a stable hostname via dynamic DNS.
|
|
9
11
|
*
|
|
10
|
-
* State for these
|
|
11
|
-
*
|
|
12
|
+
* State for these concerns lives in `<rootDir>/nat.json` (user settings) and is
|
|
13
|
+
* exposed as a single `NatStatusSnapshot` to the management UI, with one
|
|
14
|
+
* `NodeReachability` entry per hosted node.
|
|
12
15
|
*
|
|
13
16
|
* Credentials for DDNS providers are NOT stored in `nat.json`. They go through
|
|
14
17
|
* the SecretsStore (keytar, with a 0600 file fallback).
|
package/dist/nat/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/nat/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/nat/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAiJH,6EAA6E;AAC7E,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGjC,YAAY,IAAkB,EAAE,OAAe;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Orchestrator, type
|
|
2
|
-
import { type
|
|
1
|
+
import { type Orchestrator, type OrchestratorCreateResult, type OrchestratorStats } from '@serfab/cadre-provider';
|
|
2
|
+
import { type HostProcessConfig, type HostedSpawnRequest, type ManagedNodeInfo, type NodePorts, type NodeStateListener } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* The libp2p listen addresses a managed child binds — its `CADRE_LISTEN_ADDRS`, one
|
|
5
5
|
* entry per element: TCP on the `p2p` port and WebSocket on the `ws` port, both on
|
|
@@ -13,15 +13,6 @@ import { type OwnerSpawnConfig, type HostProcessConfig, type ManagedNodeInfo, ty
|
|
|
13
13
|
* (`resolveTransportOptions` in `cadre-core/src/relay-addrs.ts`).
|
|
14
14
|
*/
|
|
15
15
|
export declare function childListenAddrs(ports: Pick<NodePorts, 'p2p' | 'ws'>): string[];
|
|
16
|
-
/** Fixed friendly id for the admin's owner node. */
|
|
17
|
-
export declare const OWNER_CONTAINER_ID = "owner";
|
|
18
|
-
/** Endpoint + bearer for the owner node's loopback admin channel (6.6). */
|
|
19
|
-
export interface OwnerAdminEndpoint {
|
|
20
|
-
/** e.g. `http://127.0.0.1:<adminPort>`. */
|
|
21
|
-
baseUrl: string;
|
|
22
|
-
/** The child's `CADRE_STARTUP_TOKEN`, used as the admin bearer secret. */
|
|
23
|
-
token: string;
|
|
24
|
-
}
|
|
25
16
|
/**
|
|
26
17
|
* Runs cadre nodes as plain Node child processes on the host.
|
|
27
18
|
*
|
|
@@ -65,10 +56,10 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
65
56
|
private readonly cliEntrypoint;
|
|
66
57
|
/** Resolves push credentials fresh on every spawn (see HostProcessConfig). */
|
|
67
58
|
private readonly pushResolver?;
|
|
59
|
+
/** The public addresses a node announces, asked at every spawn (see HostProcessConfig). */
|
|
60
|
+
private readonly announceAddrs?;
|
|
68
61
|
/** State-change listeners — invoked when a handle's alive state changes. */
|
|
69
62
|
private readonly stateListeners;
|
|
70
|
-
/** Persisted spawn config for the owner node (re-spawn on demand). */
|
|
71
|
-
private ownerConfig?;
|
|
72
63
|
constructor(cfg: HostProcessConfig);
|
|
73
64
|
/**
|
|
74
65
|
* Read persisted state and re-attach to surviving children. Not part of
|
|
@@ -93,25 +84,27 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
93
84
|
resolveDockerId(idOrDockerId: string): string | undefined;
|
|
94
85
|
/**
|
|
95
86
|
* Register a state-change listener. Invoked when a handle's `alive`
|
|
96
|
-
* transitions (child exit, manual stop)
|
|
87
|
+
* transitions (create, child exit, manual stop) and once more, as `stopped`,
|
|
88
|
+
* when a handle is removed. Returns an unsubscribe fn.
|
|
97
89
|
*/
|
|
98
90
|
onStateChange(listener: NodeStateListener): () => void;
|
|
99
91
|
/**
|
|
100
|
-
* Spawn a
|
|
101
|
-
*
|
|
102
|
-
*
|
|
92
|
+
* Spawn a managed node — a hosted node for some cadre, started waiting to be
|
|
93
|
+
* claimed when the request carries a `claimSecret`, or redeeming the cadre
|
|
94
|
+
* invitation it carries as `invitation`. The node is given its own
|
|
95
|
+
* protobuf identity key inside its workdir (`ensureNodeIdentity`, reused across
|
|
103
96
|
* re-spawns of the same containerId), which is what makes its peer id stable
|
|
104
97
|
* across restarts AND what makes its node-local stores durable: `cadre-cli
|
|
105
98
|
* start` opens the file-backed bootstrap-peer, trusted-owner and strand
|
|
106
99
|
* network-state stores in the node's state directory, which defaults to the
|
|
107
100
|
* directory holding the `cadre.json` written here — the same workdir.
|
|
108
|
-
*
|
|
101
|
+
* Removing the node (`removeContainer`) deletes the workdir, so the key and
|
|
109
102
|
* every store go with it.
|
|
110
103
|
*/
|
|
111
|
-
createContainer(request:
|
|
104
|
+
createContainer(request: HostedSpawnRequest): Promise<OrchestratorCreateResult>;
|
|
112
105
|
/**
|
|
113
106
|
* Remove the working directory a spawn created for `containerId` when no
|
|
114
|
-
* handle owns it — the cleanup of last resort for a
|
|
107
|
+
* handle owns it — the cleanup of last resort for a hosted-node record that
|
|
115
108
|
* never got a `dockerId` (the host died between `ensureNodeIdentity` and the
|
|
116
109
|
* handle write, so `createContainer`'s own unwind never ran). Returns whether
|
|
117
110
|
* anything was removed.
|
|
@@ -144,33 +137,17 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
144
137
|
*/
|
|
145
138
|
private resolvePush;
|
|
146
139
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* orchestrator restart) can re-spawn it without re-supplying them.
|
|
152
|
-
*
|
|
153
|
-
* The owner node is spawned as `cadre-cli start --owner
|
|
154
|
-
* --admin-port <p> --identity-file <identityPath>` so it carries the
|
|
155
|
-
* host's libp2p identity, founds/joins the control network, and exposes the
|
|
156
|
-
* loopback admin channel the manager delegates to.
|
|
140
|
+
* The public addresses the node about to spawn announces. A hook that throws costs
|
|
141
|
+
* the node its public addresses, never its start: it still binds and is reachable
|
|
142
|
+
* on its LAN addresses, and `NatService` restarts it once the addresses it should
|
|
143
|
+
* announce differ from these.
|
|
157
144
|
*/
|
|
158
|
-
|
|
159
|
-
/** Endpoint + bearer for the owner node's admin channel, if spawned. */
|
|
160
|
-
getOwnerAdminEndpoint(): OwnerAdminEndpoint | undefined;
|
|
161
|
-
/** Whether spawn parameters for the owner node are known (persisted). */
|
|
162
|
-
hasOwnerConfig(): boolean;
|
|
163
|
-
/** Whether the given friendly/docker id refers to the owner node. */
|
|
164
|
-
isOwnerNode(idOrDockerId: string): boolean;
|
|
165
|
-
/** Stop the owner node (if running). Used on graceful shutdown. */
|
|
166
|
-
stopOwnerNode(): Promise<void>;
|
|
167
|
-
/** Stop the owner node (if running), then re-spawn it from saved config. */
|
|
168
|
-
restartOwnerNode(): Promise<ManagedNodeInfo>;
|
|
145
|
+
private announceAddrsFor;
|
|
169
146
|
/**
|
|
170
|
-
* Core spawn mechanics
|
|
147
|
+
* Core spawn mechanics behind `createContainer`.
|
|
171
148
|
*
|
|
172
149
|
* The caller has already allocated `ports` and **owns their lifetime**: this
|
|
173
|
-
* method never releases them, so
|
|
150
|
+
* method never releases them, so the caller must release on any throw out
|
|
174
151
|
* of here (it has to unwind its handle drop on the same path anyway — see
|
|
175
152
|
* `restoreDroppedHandles`).
|
|
176
153
|
*
|
|
@@ -184,7 +161,7 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
184
161
|
private launchChild;
|
|
185
162
|
/**
|
|
186
163
|
* Refuse to re-spawn `containerId` while a previous child of it may still be
|
|
187
|
-
* running.
|
|
164
|
+
* running. `createContainer` calls this as its last `await` before the handle
|
|
188
165
|
* drop, so a refusal happens while nothing has been released, no token rotated
|
|
189
166
|
* and no child launched — the caller sees an ordinary failed spawn.
|
|
190
167
|
*
|
|
@@ -202,9 +179,6 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
202
179
|
* is already bound, refuse. The pid is never killed on that evidence — it may
|
|
203
180
|
* not be ours.
|
|
204
181
|
*
|
|
205
|
-
* `overrides` are the ports the caller will override on top of the reused ones
|
|
206
|
-
* (the owner node's configured p2p port); `owner` adds the admin channel.
|
|
207
|
-
*
|
|
208
182
|
* NOTE: the probe cannot see a re-attached child still loading its modules —
|
|
209
183
|
* `cadre-cli start` writes its token and only then binds, so a child in that
|
|
210
184
|
* window shows neither, and a re-spawn launched then races it for the ports.
|
|
@@ -225,9 +199,9 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
225
199
|
/**
|
|
226
200
|
* Drop any handle left over from a previous spawn of the same `containerId`
|
|
227
201
|
* and release its ports. Handles are keyed by the per-spawn `dockerId`, so
|
|
228
|
-
* without this a re-spawn (
|
|
202
|
+
* without this a re-spawn (a hosted node's respawn) would strand the prior
|
|
229
203
|
* handle in the map forever, leaking its ports from a bounded range each
|
|
230
|
-
* time.
|
|
204
|
+
* time.
|
|
231
205
|
*
|
|
232
206
|
* DO NOT delete the workdir: the identity key and node-local stores
|
|
233
207
|
* (trusted-owner anchor, retained cold-start dial targets) live there and are
|
|
@@ -237,16 +211,16 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
237
211
|
* Releasing the ports hands them straight back to the allocator, and the
|
|
238
212
|
* re-spawn then takes those same ports as overrides (`reusedNodePorts`), so a
|
|
239
213
|
* re-spawn while the *previous* child is still listening would bind-clash.
|
|
240
|
-
*
|
|
214
|
+
* The caller must therefore never drop a live child, and does so only after
|
|
241
215
|
* {@link refuseRespawnOverLiveChild} has passed. A caller that needs to replace
|
|
242
216
|
* a live child must stop it first.
|
|
243
217
|
*
|
|
244
218
|
* **The drop is reversible.** It happens before the launch can fail, so the
|
|
245
|
-
* dropped handles are returned and
|
|
219
|
+
* dropped handles are returned and the caller restores them via
|
|
246
220
|
* {@link restoreDroppedHandles} when the launch throws — otherwise the caller
|
|
247
221
|
* would be left holding a dockerId this orchestrator no longer knows, and the
|
|
248
222
|
* node's workdir could never be reclaimed. On a *successful* spawn the drop
|
|
249
|
-
* stands: `
|
|
223
|
+
* stands: `HostedNodeService.abandonRespawn` depends on the old handle being
|
|
250
224
|
* gone by then.
|
|
251
225
|
*/
|
|
252
226
|
private dropStaleHandle;
|
|
@@ -257,10 +231,10 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
257
231
|
*
|
|
258
232
|
* **Precondition: the drop → launch window is synchronous.** Restoring is
|
|
259
233
|
* sound only because nothing can have taken those ports or run cleanup
|
|
260
|
-
* against the handle in between — `launchChild` contains no `await` and
|
|
261
|
-
*
|
|
234
|
+
* against the handle in between — `launchChild` contains no `await` and the
|
|
235
|
+
* caller resolves push credentials *before* its drop. `launchChild`'s half
|
|
262
236
|
* is enforced: its declared return type is not a Promise, so adding an
|
|
263
|
-
* `await` there is a compile error. The
|
|
237
|
+
* `await` there is a compile error. The caller's half is not — an `await`
|
|
264
238
|
* slipped between a drop and its launch silently breaks this.
|
|
265
239
|
*
|
|
266
240
|
* No `persist()` here: `state.json` is rewritten only by `launchChild` and
|
|
@@ -278,8 +252,6 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
278
252
|
private restoreDroppedHandles;
|
|
279
253
|
/** A managed node's own directory under `rootDir` — config, log, storage, identity. */
|
|
280
254
|
private workdirFor;
|
|
281
|
-
/** Locate the owner node's handle, if one has been spawned. */
|
|
282
|
-
private findOwnerHandle;
|
|
283
255
|
/**
|
|
284
256
|
* Inverse of {@link releasePorts} — hold a handle's whole port set against
|
|
285
257
|
* the allocator. Used both to rehydrate on `init` and to undo a drop whose
|
|
@@ -299,20 +271,6 @@ export declare class HostProcessOrchestrator implements Orchestrator {
|
|
|
299
271
|
getLogs(dockerId: string, tail?: number): Promise<string>;
|
|
300
272
|
private requireHandle;
|
|
301
273
|
private buildChildConfig;
|
|
302
|
-
/**
|
|
303
|
-
* Child config for the **host's own personal cadre** owner node — the opt-in
|
|
304
|
-
* "founder" persona spawned only when `ownCadre.enabled` (see
|
|
305
|
-
* docs/cadre-host.md § Two roles: donor and founder). It founds/joins the
|
|
306
|
-
* control network for the host's own `partyId` (no bootstrap peers — it is the
|
|
307
|
-
* founding node of the host's *own* cadre) and carries the host identity via
|
|
308
|
-
* `--identity-file` (passed as a spawn arg).
|
|
309
|
-
*
|
|
310
|
-
* This is NOT the node cadre-host donates to a requester. Donated nodes are
|
|
311
|
-
* generic (`createContainer` / `buildChildConfig`): they join the
|
|
312
|
-
* **requester's** cadre via bootstrap peers and pin the *requester's* owner
|
|
313
|
-
* key — they never run a host genesis.
|
|
314
|
-
*/
|
|
315
|
-
private buildOwnerChildConfig;
|
|
316
274
|
private persist;
|
|
317
275
|
private emitStateChange;
|
|
318
276
|
private toPersisted;
|