@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
|
@@ -2,105 +2,51 @@
|
|
|
2
2
|
* Fastify error handler — translates known typed errors to stable HTTP status
|
|
3
3
|
* codes and uniform `{ ok: false, error: { code, message } }` payloads.
|
|
4
4
|
*
|
|
5
|
-
* Codes (cross-referenced with `
|
|
6
|
-
* `
|
|
7
|
-
* - TrustCircleError
|
|
8
|
-
* invalid_label, invalid_token → 400
|
|
9
|
-
* not_found, already_redeemed → 404
|
|
10
|
-
* expired → 410
|
|
11
|
-
* node_unavailable → 503
|
|
12
|
-
* storage_error → 500
|
|
5
|
+
* Codes (cross-referenced with `nat/types.ts`, `update/types.ts`,
|
|
6
|
+
* `hosted/types.ts`):
|
|
13
7
|
* - NatError
|
|
14
8
|
* invalid_config, ddns_provider_unknown,
|
|
15
9
|
* ddns_credentials_missing → 400
|
|
10
|
+
* unknown_node → 404
|
|
16
11
|
* secrets_unavailable, storage_error,
|
|
17
12
|
* mapping_failed, router_unreachable,
|
|
18
13
|
* ip_detection_failed, ddns_update_failed → 500
|
|
19
|
-
* node_unavailable → 503
|
|
20
|
-
* - StrandError
|
|
21
|
-
* invalid_id → 400
|
|
22
|
-
* confirmation_required → 428
|
|
23
|
-
* node_unavailable → 503
|
|
24
|
-
* internal → 500
|
|
25
14
|
* - UpdateErrorException
|
|
26
15
|
* manifest_invalid, no_update_available,
|
|
27
16
|
* min_previous_version → 400
|
|
28
17
|
* apply_in_progress → 409
|
|
29
18
|
* signature_invalid, unsupported_state_version,
|
|
30
19
|
* apply_failed, rollback_failed, storage_error → 500
|
|
31
|
-
* -
|
|
32
|
-
* invalid_label, invalid_max_nodes,
|
|
33
|
-
* invalid_ttl → 400
|
|
34
|
-
* not_found → 404
|
|
35
|
-
* storage_error → 500
|
|
36
|
-
* - DonationError
|
|
20
|
+
* - HostedNodeError
|
|
37
21
|
* invalid_request → 400
|
|
38
|
-
* unauthorized → 401
|
|
39
|
-
* forbidden → 403
|
|
40
22
|
* not_found → 404
|
|
41
23
|
* invalid_state → 409
|
|
42
|
-
* quota_exceeded → 429
|
|
43
24
|
* orchestrator_error, storage_error → 500
|
|
44
|
-
*
|
|
45
|
-
* peer_unavailable → 503
|
|
25
|
+
* node_unavailable → 503
|
|
46
26
|
* - everything else → 500 (code "internal")
|
|
47
27
|
*/
|
|
48
28
|
import debug from 'debug';
|
|
49
|
-
import { TrustCircleError } from '../auth/types.js';
|
|
50
29
|
import { NatError } from '../nat/types.js';
|
|
51
|
-
import { StrandError } from '../strands/types.js';
|
|
52
30
|
import { UpdateErrorException } from '../update/types.js';
|
|
53
|
-
import {
|
|
31
|
+
import { HostedNodeError } from '../hosted/types.js';
|
|
54
32
|
const log = debug('cadre:host:error-handler');
|
|
55
|
-
const TRUST_STATUS = {
|
|
56
|
-
invalid_label: 400,
|
|
57
|
-
invalid_token: 400,
|
|
58
|
-
not_found: 404,
|
|
59
|
-
already_redeemed: 404,
|
|
60
|
-
expired: 410,
|
|
61
|
-
storage_error: 500,
|
|
62
|
-
node_unavailable: 503,
|
|
63
|
-
};
|
|
64
33
|
const NAT_STATUS = {
|
|
65
34
|
invalid_config: 400,
|
|
66
35
|
ddns_provider_unknown: 400,
|
|
67
36
|
ddns_credentials_missing: 400,
|
|
37
|
+
unknown_node: 404,
|
|
68
38
|
secrets_unavailable: 500,
|
|
69
39
|
storage_error: 500,
|
|
70
40
|
mapping_failed: 500,
|
|
71
41
|
router_unreachable: 500,
|
|
72
42
|
ip_detection_failed: 500,
|
|
73
43
|
ddns_update_failed: 500,
|
|
74
|
-
node_unavailable: 503,
|
|
75
44
|
};
|
|
76
|
-
|
|
77
|
-
* 428 (Precondition Required) for `confirmation_required`: the node refused a
|
|
78
|
-
* closed-strand removal because the caller had not confirmed. It is not a 400
|
|
79
|
-
* (the request was well-formed) and not a 409 (nothing conflicts) — the caller
|
|
80
|
-
* must re-send with the precondition satisfied.
|
|
81
|
-
*/
|
|
82
|
-
const STRAND_STATUS = {
|
|
83
|
-
invalid_id: 400,
|
|
84
|
-
confirmation_required: 428,
|
|
85
|
-
node_unavailable: 503,
|
|
86
|
-
internal: 500,
|
|
87
|
-
};
|
|
88
|
-
const GRANT_STATUS = {
|
|
89
|
-
invalid_label: 400,
|
|
90
|
-
invalid_max_nodes: 400,
|
|
91
|
-
invalid_ttl: 400,
|
|
92
|
-
not_found: 404,
|
|
93
|
-
storage_error: 500,
|
|
94
|
-
};
|
|
95
|
-
const DONATION_STATUS = {
|
|
96
|
-
unauthorized: 401,
|
|
97
|
-
forbidden: 403,
|
|
98
|
-
quota_exceeded: 429,
|
|
45
|
+
const HOSTED_NODE_STATUS = {
|
|
99
46
|
invalid_request: 400,
|
|
100
47
|
not_found: 404,
|
|
101
48
|
invalid_state: 409,
|
|
102
|
-
|
|
103
|
-
peer_unavailable: 503,
|
|
49
|
+
node_unavailable: 503,
|
|
104
50
|
orchestrator_error: 500,
|
|
105
51
|
storage_error: 500,
|
|
106
52
|
};
|
|
@@ -131,23 +77,14 @@ export function registerErrorHandler(app) {
|
|
|
131
77
|
});
|
|
132
78
|
}
|
|
133
79
|
function classify(err) {
|
|
134
|
-
if (err instanceof TrustCircleError) {
|
|
135
|
-
return { status: TRUST_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
136
|
-
}
|
|
137
80
|
if (err instanceof NatError) {
|
|
138
81
|
return { status: NAT_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
139
82
|
}
|
|
140
|
-
if (err instanceof StrandError) {
|
|
141
|
-
return { status: STRAND_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
142
|
-
}
|
|
143
83
|
if (err instanceof UpdateErrorException) {
|
|
144
84
|
return { status: UPDATE_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
145
85
|
}
|
|
146
|
-
if (err instanceof
|
|
147
|
-
return { status:
|
|
148
|
-
}
|
|
149
|
-
if (err instanceof DonationError) {
|
|
150
|
-
return { status: DONATION_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
86
|
+
if (err instanceof HostedNodeError) {
|
|
87
|
+
return { status: HOSTED_NODE_STATUS[err.code] ?? 500, code: err.code, message: err.message };
|
|
151
88
|
}
|
|
152
89
|
// Fastify body-parsing / validation errors have a statusCode we should honour.
|
|
153
90
|
if (typeof err.statusCode === 'number' && err.statusCode >= 400 && err.statusCode < 600) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/server/error-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/server/error-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Event types broadcast over the SPA's SSE channel.
|
|
3
3
|
*
|
|
4
|
-
* Publishers (orchestrator hook, route adapters,
|
|
4
|
+
* Publishers (orchestrator hook, route adapters, NAT change listener, the
|
|
5
|
+
* hosted-node service's change listener, update observer) call
|
|
5
6
|
* EventBus.publish; the `/api/events` route fan-outs to connected clients.
|
|
6
7
|
*/
|
|
7
8
|
import type { ContainerStatus } from '@serfab/cadre-provider';
|
|
8
|
-
import type {
|
|
9
|
+
import type { HostedNodeChangeKind } from '../../hosted/types.js';
|
|
10
|
+
import type { DirectReachability } from '../../nat/index.js';
|
|
9
11
|
export type LocalUiEvent = {
|
|
10
12
|
type: 'node-state-changed';
|
|
11
13
|
nodeId: string;
|
|
12
14
|
status: ContainerStatus;
|
|
13
15
|
} | {
|
|
14
|
-
type: '
|
|
15
|
-
kind:
|
|
16
|
-
|
|
17
|
-
type: 'strands-changed';
|
|
18
|
-
kind: 'removed';
|
|
19
|
-
} | {
|
|
20
|
-
type: 'grants-changed';
|
|
21
|
-
kind: 'issued' | 'revoked' | 'terminated';
|
|
16
|
+
type: 'hosted-nodes-changed';
|
|
17
|
+
kind: HostedNodeChangeKind;
|
|
18
|
+
nodeId: string;
|
|
22
19
|
} | {
|
|
23
20
|
type: 'connectivity-changed';
|
|
24
|
-
portMode: PortForwardMode;
|
|
25
21
|
directReachability: DirectReachability;
|
|
26
22
|
} | {
|
|
27
23
|
type: 'update-available';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Event types broadcast over the SPA's SSE channel.
|
|
3
3
|
*
|
|
4
|
-
* Publishers (orchestrator hook, route adapters,
|
|
4
|
+
* Publishers (orchestrator hook, route adapters, NAT change listener, the
|
|
5
|
+
* hosted-node service's change listener, update observer) call
|
|
5
6
|
* EventBus.publish; the `/api/events` route fan-outs to connected clients.
|
|
6
7
|
*/
|
|
7
8
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/server/events/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/server/events/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -3,34 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `createLocalUiServer(opts)` wires:
|
|
5
5
|
* - the origin guard + error handler
|
|
6
|
-
* - existing
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
6
|
+
* - existing NAT / update typed handlers, mounted at `/nat/*`, `/update/*`
|
|
7
|
+
* (the CLI contract)
|
|
8
|
+
* - the `/api/*` routes (status, nodes, hosted nodes, settings, events)
|
|
9
9
|
* - the static SPA mount at `/`
|
|
10
10
|
*
|
|
11
11
|
* Callers (cadre-host start) own the subsystems and pass them in. The
|
|
12
12
|
* server doesn't construct them — start has to own their lifecycle anyway
|
|
13
|
-
* (orchestrator init,
|
|
13
|
+
* (orchestrator init, NAT bring-up, update timer).
|
|
14
14
|
*/
|
|
15
15
|
import type { FastifyInstance } from 'fastify';
|
|
16
16
|
import type { HostProcessOrchestrator } from '../orchestrator/index.js';
|
|
17
|
-
import type { TrustCircleService } from '../auth/index.js';
|
|
18
17
|
import type { NatService } from '../nat/index.js';
|
|
19
|
-
import type { StrandService } from '../strands/index.js';
|
|
20
18
|
import type { UpdateService } from '../update/index.js';
|
|
21
|
-
import type {
|
|
19
|
+
import type { HostedNodeService } from '../hosted/index.js';
|
|
22
20
|
import { EventBus } from './events/bus.js';
|
|
23
21
|
import { HostSettingsStore } from './settings-store.js';
|
|
24
|
-
/**
|
|
25
|
-
* The host's own-cadre services. All three or none: they share the owner node,
|
|
26
|
-
* and grouping them makes the role `/api/status` reports impossible to disagree
|
|
27
|
-
* with the surfaces actually mounted.
|
|
28
|
-
*/
|
|
29
|
-
export interface FounderServices {
|
|
30
|
-
trustCircle: TrustCircleService;
|
|
31
|
-
nat: NatService;
|
|
32
|
-
strands: StrandService;
|
|
33
|
-
}
|
|
34
22
|
export interface LocalUiServerOptions {
|
|
35
23
|
/** Configured UI port from host.config.json. May be re-bound on collision. */
|
|
36
24
|
uiPort: number;
|
|
@@ -38,29 +26,16 @@ export interface LocalUiServerOptions {
|
|
|
38
26
|
dataDir: string;
|
|
39
27
|
/** Wired dependencies — all owned by the caller. */
|
|
40
28
|
orchestrator: HostProcessOrchestrator;
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
* founder role). Absent in donor-only mode, where `/auth/*`, `/nat/*` and
|
|
44
|
-
* `/api/strands` stay unmounted and 404 through the static handler, and
|
|
45
|
-
* `/api/status` reports `role: 'donor'`.
|
|
46
|
-
*/
|
|
47
|
-
founder?: FounderServices;
|
|
29
|
+
/** The NAT layer: every node the host runs gets its ports mapped, so `/nat/*` always mounts. */
|
|
30
|
+
nat: NatService;
|
|
48
31
|
/** Optional — 6.4.2 lands this; nullable while still iterating. */
|
|
49
32
|
update?: UpdateService;
|
|
50
33
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* exercise donations need not wire it.
|
|
55
|
-
*/
|
|
56
|
-
grants?: GrantService;
|
|
57
|
-
/**
|
|
58
|
-
* Donation lifecycle service. When present (alongside `grants`), mounts the
|
|
59
|
-
* bearer-gated grantee-facing provisioning surface at `/grants`
|
|
60
|
-
* (provision / peer / seed / terminate). Optional so callers/tests that don't
|
|
61
|
-
* exercise the donor path need not wire it.
|
|
34
|
+
* The hosted-node service. When present, mounts `/api/hosted-nodes` and
|
|
35
|
+
* forwards the service's changes to the bus as `hosted-nodes-changed`.
|
|
36
|
+
* Optional so callers/tests that don't exercise hosted nodes need not wire it.
|
|
62
37
|
*/
|
|
63
|
-
|
|
38
|
+
hostedNodes?: HostedNodeService;
|
|
64
39
|
/** Settings I/O facade. Defaults to a new one rooted at `dataDir`. */
|
|
65
40
|
settingsStore?: HostSettingsStore;
|
|
66
41
|
/** Bus instance — pass the same one to subsystems that publish events. */
|
|
@@ -96,4 +71,3 @@ export { EventBus } from './events/bus.js';
|
|
|
96
71
|
export type { LocalUiEventListener } from './events/bus.js';
|
|
97
72
|
export type { LocalUiEvent, LocalUiEventType } from './events/types.js';
|
|
98
73
|
export { HostSettingsStore } from './settings-store.js';
|
|
99
|
-
export type { HostRole } from './routes/status.js';
|
package/dist/server/index.js
CHANGED
|
@@ -3,41 +3,34 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `createLocalUiServer(opts)` wires:
|
|
5
5
|
* - the origin guard + error handler
|
|
6
|
-
* - existing
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
6
|
+
* - existing NAT / update typed handlers, mounted at `/nat/*`, `/update/*`
|
|
7
|
+
* (the CLI contract)
|
|
8
|
+
* - the `/api/*` routes (status, nodes, hosted nodes, settings, events)
|
|
9
9
|
* - the static SPA mount at `/`
|
|
10
10
|
*
|
|
11
11
|
* Callers (cadre-host start) own the subsystems and pass them in. The
|
|
12
12
|
* server doesn't construct them — start has to own their lifecycle anyway
|
|
13
|
-
* (orchestrator init,
|
|
13
|
+
* (orchestrator init, NAT bring-up, update timer).
|
|
14
14
|
*/
|
|
15
|
-
import { createTrustCircleHandlers } from '../auth/index.js';
|
|
16
15
|
import { createNatHandlers } from '../nat/index.js';
|
|
17
|
-
import { createStrandHandlers } from '../strands/index.js';
|
|
18
16
|
import { createUpdateHandlers } from '../update/index.js';
|
|
19
|
-
import { createGrantAdminHandlers } from '../donation/index.js';
|
|
20
17
|
import { EventBus } from './events/bus.js';
|
|
21
18
|
import { registerSseRoute } from './events/sse-route.js';
|
|
22
19
|
import { registerErrorHandler } from './error-handler.js';
|
|
23
20
|
import { registerOriginGuard } from './origin-guard.js';
|
|
24
21
|
import { registerStaticMount } from './static.js';
|
|
25
22
|
import { buildFastify, startListening, stopListening } from './server.js';
|
|
26
|
-
import { registerNatRoutes } from './routes/nat.js';
|
|
27
|
-
import { registerTrustCircleRoutes } from './routes/trust-circle.js';
|
|
28
|
-
import { registerStrandRoutes } from './routes/strands.js';
|
|
23
|
+
import { registerNatRoutes, publishConnectivity } from './routes/nat.js';
|
|
29
24
|
import { registerUpdateRoutes } from './routes/update.js';
|
|
30
25
|
import { registerStatusRoute } from './routes/status.js';
|
|
31
26
|
import { registerNodesRoutes } from './routes/nodes.js';
|
|
32
27
|
import { registerSettingsRoutes } from './routes/settings.js';
|
|
33
|
-
import {
|
|
34
|
-
import { registerGrantsRoutes } from './routes/grants.js';
|
|
28
|
+
import { registerHostedNodesRoutes } from './routes/hosted-nodes.js';
|
|
35
29
|
import { HostSettingsStore } from './settings-store.js';
|
|
36
30
|
/** How often to poll UpdateService.getState() looking for new versions. */
|
|
37
31
|
const UPDATE_OBSERVER_INTERVAL_MS = 60000;
|
|
38
32
|
export function createLocalUiServer(opts) {
|
|
39
|
-
const {
|
|
40
|
-
const role = founder ? 'founder' : 'donor';
|
|
33
|
+
const { nat } = opts;
|
|
41
34
|
const events = opts.events ?? new EventBus();
|
|
42
35
|
const settingsStore = opts.settingsStore ?? new HostSettingsStore({ dataDir: opts.dataDir });
|
|
43
36
|
const app = buildFastify();
|
|
@@ -51,31 +44,17 @@ export function createLocalUiServer(opts) {
|
|
|
51
44
|
});
|
|
52
45
|
registerStatusRoute(app, {
|
|
53
46
|
orchestrator: opts.orchestrator,
|
|
54
|
-
|
|
55
|
-
...(founder ? { trustCircle: founder.trustCircle, nat: founder.nat } : {}),
|
|
47
|
+
nat,
|
|
56
48
|
...(opts.update ? { update: opts.update } : {}),
|
|
57
49
|
});
|
|
58
|
-
registerNodesRoutes(app, { orchestrator: opts.orchestrator
|
|
59
|
-
registerSettingsRoutes(app, { settingsStore,
|
|
60
|
-
|
|
61
|
-
// personal cadre. In donor-only mode they're left unmounted, so `/auth/*`,
|
|
62
|
-
// `/nat/*` and `/api/strands` fall through to the static not-found handler and
|
|
63
|
-
// 404 (see static.ts).
|
|
64
|
-
if (founder) {
|
|
65
|
-
registerTrustCircleRoutes(app, { handlers: createTrustCircleHandlers(founder.trustCircle), events });
|
|
66
|
-
registerNatRoutes(app, { handlers: createNatHandlers(founder.nat), events });
|
|
67
|
-
registerStrandRoutes(app, { handlers: createStrandHandlers(founder.strands), events });
|
|
68
|
-
}
|
|
50
|
+
registerNodesRoutes(app, { orchestrator: opts.orchestrator });
|
|
51
|
+
registerSettingsRoutes(app, { settingsStore, nat, ...(opts.update ? { update: opts.update } : {}) });
|
|
52
|
+
registerNatRoutes(app, { handlers: createNatHandlers(nat), events });
|
|
69
53
|
if (opts.update) {
|
|
70
54
|
registerUpdateRoutes(app, { handlers: createUpdateHandlers(opts.update), events });
|
|
71
55
|
}
|
|
72
|
-
if (opts.
|
|
73
|
-
|
|
74
|
-
// Grantee-facing provisioning surface needs both the donation service and a
|
|
75
|
-
// grant validator (the GrantService doubles as the validator).
|
|
76
|
-
if (opts.donations) {
|
|
77
|
-
registerGrantsRoutes(app, { donations: opts.donations, grants: opts.grants });
|
|
78
|
-
}
|
|
56
|
+
if (opts.hostedNodes) {
|
|
57
|
+
registerHostedNodesRoutes(app, { hostedNodes: opts.hostedNodes });
|
|
79
58
|
}
|
|
80
59
|
// Static mount registers as the not-found handler — declared last so the
|
|
81
60
|
// API paths above win.
|
|
@@ -106,21 +85,24 @@ export function createLocalUiServer(opts) {
|
|
|
106
85
|
status: info.status === 'running' ? 'running' : 'stopped',
|
|
107
86
|
});
|
|
108
87
|
}));
|
|
88
|
+
// NAT → bus adapter: a mapping that completes after a spawn, an IP change
|
|
89
|
+
// or a lease the router dropped all change the snapshot without any
|
|
90
|
+
// route being called; the SPA follows them through this.
|
|
91
|
+
teardown.push(nat.onChange((snap) => { publishConnectivity(events, snap); }));
|
|
92
|
+
// Hosted nodes → bus adapter: a join, a claim the watcher noticed, a
|
|
93
|
+
// removal, a respawn or a give-up — the routes publish nothing themselves.
|
|
94
|
+
if (opts.hostedNodes) {
|
|
95
|
+
teardown.push(opts.hostedNodes.onChange((change) => {
|
|
96
|
+
events.publish({ type: 'hosted-nodes-changed', kind: change.kind, nodeId: change.id });
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
109
99
|
// One-shot connectivity publish — the SPA will get a sane initial
|
|
110
|
-
// signal even if no settings have changed yet this session.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
type: 'connectivity-changed',
|
|
117
|
-
portMode: snap.portMode,
|
|
118
|
-
directReachability: snap.directReachability,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// NatService.start may not have completed; harmless to skip.
|
|
123
|
-
}
|
|
100
|
+
// signal even if no settings have changed yet this session.
|
|
101
|
+
try {
|
|
102
|
+
publishConnectivity(events, nat.getStatus());
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// NatService.start may not have completed; harmless to skip.
|
|
124
106
|
}
|
|
125
107
|
// Update observer: poll UpdateService.getState() every 60 s and emit
|
|
126
108
|
// `update-available` when `available.version` changes. Cheap, avoids
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/api/hosted-nodes` — the host's "Join a cadre" action and the nodes it made.
|
|
3
|
+
* Loopback, no bearer: same-machine admin, matching the local-UI "no login"
|
|
4
|
+
* posture. Clients: the `cadre-host join` / `cadre-host node` CLI and the local
|
|
5
|
+
* UI.
|
|
6
|
+
*
|
|
7
|
+
* GET /api/hosted-nodes every hosted node (secret and invitation stripped)
|
|
8
|
+
* POST /api/hosted-nodes { invitation? } start a node waiting to be claimed, or one
|
|
9
|
+
* that redeems the invitation → 201 { node }
|
|
10
|
+
* GET /api/hosted-nodes/:id one node
|
|
11
|
+
* GET /api/hosted-nodes/:id/claim the QR payload: 409 unless unclaimed, 503 until the child answers
|
|
12
|
+
* DELETE /api/hosted-nodes/:id stop the node and delete its data → 204
|
|
13
|
+
* POST /api/hosted-nodes/:id/reset remove, then start a fresh node → 201 { node }
|
|
14
|
+
* POST /api/hosted-nodes/:id/retry start an invitation node again after no member
|
|
15
|
+
* could be reached → { node }; 409 unless so
|
|
16
|
+
*
|
|
17
|
+
* Responses use the `/api/*` envelope (`{ ok, data }`); errors come from
|
|
18
|
+
* `HostedNodeError`, which `server/error-handler.ts` maps. The mutations publish
|
|
19
|
+
* nothing themselves: the service reports every change through its listener,
|
|
20
|
+
* which `server/index.ts` wires to the bus as `hosted-nodes-changed`, so a
|
|
21
|
+
* change the watcher or the supervisor makes reaches the SPA the same way.
|
|
22
|
+
*/
|
|
23
|
+
import type { FastifyInstance } from 'fastify';
|
|
24
|
+
import type { HostedNodeService } from '../../hosted/hosted-node-service.js';
|
|
25
|
+
export interface HostedNodesRoutesOptions {
|
|
26
|
+
hostedNodes: HostedNodeService;
|
|
27
|
+
}
|
|
28
|
+
export declare function registerHostedNodesRoutes(app: FastifyInstance, opts: HostedNodesRoutesOptions): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/api/hosted-nodes` — the host's "Join a cadre" action and the nodes it made.
|
|
3
|
+
* Loopback, no bearer: same-machine admin, matching the local-UI "no login"
|
|
4
|
+
* posture. Clients: the `cadre-host join` / `cadre-host node` CLI and the local
|
|
5
|
+
* UI.
|
|
6
|
+
*
|
|
7
|
+
* GET /api/hosted-nodes every hosted node (secret and invitation stripped)
|
|
8
|
+
* POST /api/hosted-nodes { invitation? } start a node waiting to be claimed, or one
|
|
9
|
+
* that redeems the invitation → 201 { node }
|
|
10
|
+
* GET /api/hosted-nodes/:id one node
|
|
11
|
+
* GET /api/hosted-nodes/:id/claim the QR payload: 409 unless unclaimed, 503 until the child answers
|
|
12
|
+
* DELETE /api/hosted-nodes/:id stop the node and delete its data → 204
|
|
13
|
+
* POST /api/hosted-nodes/:id/reset remove, then start a fresh node → 201 { node }
|
|
14
|
+
* POST /api/hosted-nodes/:id/retry start an invitation node again after no member
|
|
15
|
+
* could be reached → { node }; 409 unless so
|
|
16
|
+
*
|
|
17
|
+
* Responses use the `/api/*` envelope (`{ ok, data }`); errors come from
|
|
18
|
+
* `HostedNodeError`, which `server/error-handler.ts` maps. The mutations publish
|
|
19
|
+
* nothing themselves: the service reports every change through its listener,
|
|
20
|
+
* which `server/index.ts` wires to the bus as `hosted-nodes-changed`, so a
|
|
21
|
+
* change the watcher or the supervisor makes reaches the SPA the same way.
|
|
22
|
+
*/
|
|
23
|
+
import { HostedNodeError } from '../../hosted/types.js';
|
|
24
|
+
export function registerHostedNodesRoutes(app, opts) {
|
|
25
|
+
const { hostedNodes } = opts;
|
|
26
|
+
app.get('/api/hosted-nodes', async () => {
|
|
27
|
+
return { ok: true, data: { nodes: hostedNodes.list() } };
|
|
28
|
+
});
|
|
29
|
+
app.post('/api/hosted-nodes', async (request, reply) => {
|
|
30
|
+
const node = await hostedNodes.join(joinOptionsOf(request.body));
|
|
31
|
+
return reply.status(201).send({ ok: true, data: { node } });
|
|
32
|
+
});
|
|
33
|
+
app.get('/api/hosted-nodes/:id', async (request, reply) => {
|
|
34
|
+
const node = hostedNodes.get(request.params.id);
|
|
35
|
+
if (!node) {
|
|
36
|
+
return reply.status(404).send({ ok: false, error: { code: 'not_found', message: `No such hosted node: ${request.params.id}` } });
|
|
37
|
+
}
|
|
38
|
+
return { ok: true, data: { node } };
|
|
39
|
+
});
|
|
40
|
+
app.get('/api/hosted-nodes/:id/claim', async (request) => {
|
|
41
|
+
return { ok: true, data: await hostedNodes.claimDetails(request.params.id) };
|
|
42
|
+
});
|
|
43
|
+
app.delete('/api/hosted-nodes/:id', async (request, reply) => {
|
|
44
|
+
await hostedNodes.remove(request.params.id);
|
|
45
|
+
return reply.status(204).send();
|
|
46
|
+
});
|
|
47
|
+
app.post('/api/hosted-nodes/:id/reset', async (request, reply) => {
|
|
48
|
+
const node = await hostedNodes.reset(request.params.id);
|
|
49
|
+
return reply.status(201).send({ ok: true, data: { node } });
|
|
50
|
+
});
|
|
51
|
+
app.post('/api/hosted-nodes/:id/retry', async (request) => {
|
|
52
|
+
return { ok: true, data: { node: await hostedNodes.retry(request.params.id) } };
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** The join body: none (or `{}`) for a node waiting to be claimed, `{ invitation }` for one that redeems it. */
|
|
56
|
+
function joinOptionsOf(body) {
|
|
57
|
+
const fields = (body ?? {});
|
|
58
|
+
if (typeof fields !== 'object' || Array.isArray(fields)) {
|
|
59
|
+
throw new HostedNodeError('invalid_request', 'The body must be a JSON object');
|
|
60
|
+
}
|
|
61
|
+
if (fields.invitation === undefined)
|
|
62
|
+
return {};
|
|
63
|
+
if (typeof fields.invitation !== 'string' || fields.invitation.trim() === '') {
|
|
64
|
+
throw new HostedNodeError('invalid_request', '`invitation` must be the invitation text the owner\'s app copied');
|
|
65
|
+
}
|
|
66
|
+
return { invitation: fields.invitation };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=hosted-nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosted-nodes.js","sourceRoot":"","sources":["../../../src/server/routes/hosted-nodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NAT/DDNS HTTP routes — thin adapters around `NatHandlers`
|
|
3
3
|
* (`createNatHandlers(service)`). Side-effects (settings change, reachability
|
|
4
|
-
* re-test, DDNS reconfiguration) emit a `connectivity-changed`
|
|
4
|
+
* re-test, DDNS reconfiguration, a manual forward) emit a `connectivity-changed`
|
|
5
|
+
* bus event. The service's own change listener covers the changes that happen
|
|
6
|
+
* on their own (a mapping completing after a spawn, an IP change) — see
|
|
7
|
+
* `server/index.ts`.
|
|
5
8
|
*
|
|
6
9
|
* Mount path: `/nat/*` — matches the existing CLI (cadre-host nat ...).
|
|
7
10
|
*/
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NAT/DDNS HTTP routes — thin adapters around `NatHandlers`
|
|
3
3
|
* (`createNatHandlers(service)`). Side-effects (settings change, reachability
|
|
4
|
-
* re-test, DDNS reconfiguration) emit a `connectivity-changed`
|
|
4
|
+
* re-test, DDNS reconfiguration, a manual forward) emit a `connectivity-changed`
|
|
5
|
+
* bus event. The service's own change listener covers the changes that happen
|
|
6
|
+
* on their own (a mapping completing after a spawn, an IP change) — see
|
|
7
|
+
* `server/index.ts`.
|
|
5
8
|
*
|
|
6
9
|
* Mount path: `/nat/*` — matches the existing CLI (cadre-host nat ...).
|
|
7
10
|
*/
|
|
@@ -31,11 +34,19 @@ export function registerNatRoutes(app, opts) {
|
|
|
31
34
|
publishConnectivity(events, snap);
|
|
32
35
|
return snap;
|
|
33
36
|
});
|
|
37
|
+
// The ports the user forwarded on their router for one node. `null` clears a
|
|
38
|
+
// port; both cleared removes the entry. Unknown node → 404 unknown_node; a
|
|
39
|
+
// body that is not an object, or a port outside 1–65535 → 400 invalid_config
|
|
40
|
+
// (all from the service, which reads only `tcp` and `ws`).
|
|
41
|
+
app.put('/nat/nodes/:nodeId/forward', async (request) => {
|
|
42
|
+
const snap = await handlers.putForward(request.params.nodeId, (request.body ?? {}));
|
|
43
|
+
publishConnectivity(events, snap);
|
|
44
|
+
return snap;
|
|
45
|
+
});
|
|
34
46
|
}
|
|
35
47
|
export function publishConnectivity(events, snap) {
|
|
36
48
|
events.publish({
|
|
37
49
|
type: 'connectivity-changed',
|
|
38
|
-
portMode: snap.portMode,
|
|
39
50
|
directReachability: snap.directReachability,
|
|
40
51
|
});
|
|
41
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nat.js","sourceRoot":"","sources":["../../../src/server/routes/nat.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"nat.js","sourceRoot":"","sources":["../../../src/server/routes/nat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,MAAM,UAAU,iBAAiB,CAAC,GAAoB,EAAE,IAAsB;IAC5E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAElC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAEzD,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC/C,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAEpE,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAK/B,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;YAClC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;YACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;YACzB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,KAAK;SACnD,CAAC,CAAC;QACH,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAA2D,CAAC;QAC5F,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9C,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,2EAA2E;IAC3E,6EAA6E;IAC7E,2DAA2D;IAC3D,GAAG,CAAC,GAAG,CAAiC,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACtF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAuB,CAAC,CAAC;QAC1G,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAgB,EAAE,IAAuB;IAC3E,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,sBAAsB;QAC5B,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;KAC5C,CAAC,CAAC;AACL,CAAC"}
|