@camstack/server 1.2.594 → 1.2.596
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon-root-inventory.js +50 -11
- package/dist/agent/addon-scan.js +44 -6
- package/dist/agent/agent-addon-runtime.js +8 -3
- package/dist/agent/agent-addon-updates.js +52 -12
- package/dist/agent/agent-cap-dispatch-service.js +5 -3
- package/dist/agent/agent-config.js +42 -7
- package/dist/agent/agent-deploy-swap.js +41 -5
- package/dist/agent/agent-group-runner.js +47 -8
- package/dist/agent/agent-http-auth.js +22 -10
- package/dist/agent/agent-http.js +113 -64
- package/dist/agent/agent-hub-addon-update.js +16 -10
- package/dist/agent/agent-hub-registration.js +7 -4
- package/dist/agent/agent-infra-capabilities.js +9 -5
- package/dist/agent/agent-json-file.js +42 -5
- package/dist/agent/agent-mesh-gate.js +8 -5
- package/dist/agent/agent-node-certificates.js +28 -25
- package/dist/agent/agent-pairing-local.js +47 -10
- package/dist/agent/agent-pairing-routes.js +20 -16
- package/dist/agent/agent-pairing-store.js +58 -18
- package/dist/agent/agent-reconnect.js +4 -1
- package/dist/agent/agent-service.js +71 -35
- package/dist/agent/agent-sniffing-listener.js +48 -11
- package/dist/agent/agent-undeploy.js +41 -5
- package/dist/agent/agent-update-routes.js +19 -14
- package/dist/agent/agent-update-service.js +80 -38
- package/dist/agent/apply-model-distribution.js +4 -1
- package/dist/agent/apply-stage-dev-uploads.js +9 -6
- package/dist/agent/derive-hub-url.js +8 -3
- package/dist/agent/fetch-bundle-from-hub.js +9 -6
- package/dist/agent/hubs-found.js +43 -6
- package/dist/agent/infra-boot-guard.js +4 -1
- package/dist/agent/infra-boot-plan.js +6 -2
- package/dist/agent/main.js +183 -148
- package/dist/agent/register-agent-cap-dispatch.js +6 -3
- package/dist/agent/serial-queue.js +7 -2
- package/dist/agent-status-page.js +4 -1
- package/dist/api/addon-upload.js +61 -22
- package/dist/api/agent-addon-delivery.js +11 -6
- package/dist/api/auth-whoami.js +4 -1
- package/dist/api/backup-download-pump.js +9 -5
- package/dist/api/backup-download.js +10 -7
- package/dist/api/core/addon-settings.router.js +19 -16
- package/dist/api/core/agent-pairing.router.js +79 -76
- package/dist/api/core/agents.router.js +24 -21
- package/dist/api/core/auth-admin-tokens.procedures.js +52 -48
- package/dist/api/core/auth-device-cert.procedures.js +67 -62
- package/dist/api/core/auth-limits.js +25 -16
- package/dist/api/core/auth-reauth.procedures.js +37 -32
- package/dist/api/core/auth-revoke-credentials.procedures.js +26 -22
- package/dist/api/core/auth-sessions.procedures.js +56 -52
- package/dist/api/core/auth.router.js +304 -300
- package/dist/api/core/cap-providers.js +121 -74
- package/dist/api/core/capabilities.router.js +37 -34
- package/dist/api/core/capability-preference-writes.js +17 -10
- package/dist/api/core/certificates.router.js +109 -106
- package/dist/api/core/cluster-nodes.router.js +18 -15
- package/dist/api/core/collection-preference.js +6 -2
- package/dist/api/core/event-bus-proxy.router.js +37 -34
- package/dist/api/core/failure-contributions.js +8 -4
- package/dist/api/core/hwaccel.router.js +20 -17
- package/dist/api/core/integration-secrets.js +12 -8
- package/dist/api/core/lifecycle-job-runner.js +49 -13
- package/dist/api/core/live-events.router.js +32 -29
- package/dist/api/core/load-contributions.js +8 -4
- package/dist/api/core/logging-settings.js +43 -30
- package/dist/api/core/logs.router.js +43 -40
- package/dist/api/core/notifications.router.js +18 -15
- package/dist/api/core/public-event-filter.js +8 -4
- package/dist/api/core/repl.router.js +21 -18
- package/dist/api/core/request-census-settings.js +16 -11
- package/dist/api/core/server-management.provider.js +4 -1
- package/dist/api/core/server-name.js +17 -9
- package/dist/api/core/site-location.js +24 -16
- package/dist/api/core/stream-probe.router.js +24 -21
- package/dist/api/core/system-events.router.js +26 -23
- package/dist/api/cors/cors-policy.js +29 -20
- package/dist/api/cors/register-cors-policy.js +14 -9
- package/dist/api/deploy-stage-registry.js +10 -6
- package/dist/api/dev-uploads-bundle.js +50 -12
- package/dist/api/health/adaptive-probe.routes.js +13 -9
- package/dist/api/health/health.routes.js +13 -8
- package/dist/api/hub-cluster-url.js +9 -3
- package/dist/api/model-distributor.js +50 -12
- package/dist/api/oauth2/consent-page.js +13 -10
- package/dist/api/oauth2/oauth2-routes.js +25 -17
- package/dist/api/oauth2/private-host.js +4 -1
- package/dist/api/server-upload-propagate.js +51 -15
- package/dist/api/server-upload.js +50 -13
- package/dist/api/sse-no-compression.js +4 -1
- package/dist/api/static/frame-policy.js +9 -4
- package/dist/api/static/precompressed-asset.js +57 -15
- package/dist/api/static/spa-mount.js +47 -8
- package/dist/api/static/spa-static.js +12 -5
- package/dist/api/tarball-manifest.js +44 -7
- package/dist/api/trpc/cap-mount-helpers.js +12 -7
- package/dist/api/trpc/cap-route-error-formatter.js +13 -10
- package/dist/api/trpc/cap-router-runtime.js +51 -40
- package/dist/api/trpc/client-ip.js +20 -9
- package/dist/api/trpc/core-cap-bridge.js +42 -32
- package/dist/api/trpc/device-collection-dispatch.js +27 -23
- package/dist/api/trpc/device-config-secret-redaction.js +40 -24
- package/dist/api/trpc/generated-cap-mounts.js +225 -219
- package/dist/api/trpc/generated-cap-routers.js +5167 -4852
- package/dist/api/trpc/http-request-census-hook.js +11 -8
- package/dist/api/trpc/http-request-census.js +41 -34
- package/dist/api/trpc/http-request-census.singleton.js +8 -4
- package/dist/api/trpc/localized-schema-paths.js +4 -1
- package/dist/api/trpc/principal-visibility.js +22 -14
- package/dist/api/trpc/remote-addon-update-grant.js +4 -1
- package/dist/api/trpc/scope-access.js +15 -10
- package/dist/api/trpc/server-provided-caps.js +7 -3
- package/dist/api/trpc/share-view-access.js +14 -6
- package/dist/api/trpc/trpc-error-device-tags.js +6 -3
- package/dist/api/trpc/trpc-error-principal.js +6 -2
- package/dist/api/trpc/trpc.context.js +25 -20
- package/dist/api/trpc/trpc.middleware.js +46 -38
- package/dist/api/trpc/trpc.router.js +99 -58
- package/dist/api/trpc/user-error.js +8 -5
- package/dist/api/trpc/ws-request-census.js +24 -17
- package/dist/api/trpc/ws-slow-consumer-guard.js +16 -11
- package/dist/api/upload-auth.js +9 -5
- package/dist/auth/addon-route-jwt-gate.js +7 -4
- package/dist/auth/addon-route-share-gate.js +12 -7
- package/dist/auth/app-confirm-page.js +22 -17
- package/dist/auth/app-confirm-routes.js +31 -26
- package/dist/auth/app-confirmations.js +44 -7
- package/dist/auth/app-page-shell.js +30 -17
- package/dist/auth/app-page-strings.js +17 -11
- package/dist/auth/app-passkey-page.js +21 -16
- package/dist/auth/app-passkey-routes.js +41 -37
- package/dist/auth/app-refused-route.js +18 -13
- package/dist/auth/auth-network-policy.js +15 -11
- package/dist/auth/auth-provider-gate.js +9 -4
- package/dist/auth/auth-rate-limit.js +7 -3
- package/dist/auth/client-address.js +9 -6
- package/dist/auth/device-enroll-proofs.js +43 -6
- package/dist/auth/external-link-intents.js +7 -3
- package/dist/auth/hub-sessions.js +12 -6
- package/dist/auth/native-link-completions.js +11 -7
- package/dist/auth/native-return.js +13 -9
- package/dist/auth/passkey-provider.js +32 -26
- package/dist/auth/second-factors.js +10 -6
- package/dist/auth/session-connections.js +12 -6
- package/dist/auth/session-cookie.js +23 -12
- package/dist/auth/session-lifetimes.js +12 -8
- package/dist/auth/session-mint.js +11 -4
- package/dist/auth/sso-finish-app.js +16 -13
- package/dist/auth/sso-finish-deps.js +27 -21
- package/dist/auth/sso-finish.js +38 -28
- package/dist/auth/sso-routes.js +25 -22
- package/dist/auth/used-bridge-ids.js +5 -1
- package/dist/boot/boot-config.js +55 -16
- package/dist/boot/init-sequence.js +4 -1
- package/dist/boot/integration-id-backfill.js +8 -3
- package/dist/boot/platform-keychain-key.js +42 -5
- package/dist/boot/post-boot.service.js +18 -14
- package/dist/boot/reconcile-lifecycle-jobs.js +6 -3
- package/dist/boot/retired-public-url-env.js +8 -4
- package/dist/bootstrap-packages.js +4 -1
- package/dist/closure-node-modules.js +38 -2
- package/dist/core/addon/addon-call-gateway.js +5 -1
- package/dist/core/addon/addon-package.service.js +123 -83
- package/dist/core/addon/addon-process-view.js +6 -2
- package/dist/core/addon/addon-realign-plan.js +4 -1
- package/dist/core/addon/addon-registry.service.js +187 -146
- package/dist/core/addon/addon-row-manifest.js +4 -1
- package/dist/core/addon/addon-search.service.js +7 -3
- package/dist/core/addon/addon-settings-provider.js +3 -1
- package/dist/core/addon/addon-uninstall.js +11 -4
- package/dist/core/addon/addon.tokens.js +5 -2
- package/dist/core/addon/device-meta-mirror.js +13 -8
- package/dist/core/addon/forked-custom-actions.js +11 -6
- package/dist/core/addon/integration-visibility.js +6 -3
- package/dist/core/addon/materialize-route-path.js +4 -1
- package/dist/core/addon/package-dir-utils.js +45 -8
- package/dist/core/addon/prune-misplaced-addons.js +43 -5
- package/dist/core/addon/runner-convergence.js +4 -1
- package/dist/core/addon/runner-serialization.js +4 -1
- package/dist/core/addon/runner-spawn-fanout.js +8 -3
- package/dist/core/addon/settings-door-wiring.js +8 -5
- package/dist/core/addon/single-flight-refresh.js +4 -1
- package/dist/core/addon-bridge/addon-bridge.service.js +44 -7
- package/dist/core/addon-pages/addon-pages.service.js +40 -3
- package/dist/core/addon-widgets/addon-widgets.service.js +42 -4
- package/dist/core/agent/agent-addon-backfill.js +17 -9
- package/dist/core/agent/agent-delivery-ledger.js +7 -3
- package/dist/core/agent/agent-liveness-event.js +6 -2
- package/dist/core/agent/agent-pairing-http.js +45 -41
- package/dist/core/agent/agent-registry.service.js +89 -50
- package/dist/core/agent/cluster-node-history-mirror.js +7 -3
- package/dist/core/agent/cluster-node-history-store.js +35 -31
- package/dist/core/agent/hub-agent-pairing.js +5 -1
- package/dist/core/agent/node-certificates-client.js +6 -3
- package/dist/core/agent/node-directory.js +4 -1
- package/dist/core/app-links/well-known-app-links.js +6 -2
- package/dist/core/auth/auth.service.js +8 -3
- package/dist/core/auth/handoff-code.service.js +49 -11
- package/dist/core/auth/record-kinds.js +19 -16
- package/dist/core/auth/share-token.service.js +79 -42
- package/dist/core/capability/capability.service.js +5 -1
- package/dist/core/config/config.schema.js +6 -1
- package/dist/core/config/config.service.js +6 -2
- package/dist/core/events/event-bus.service.js +7 -3
- package/dist/core/feature/feature.service.js +6 -2
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +10 -5
- package/dist/core/lifecycle/lifecycle-state-machine.js +5 -1
- package/dist/core/logging/log-ring-buffer.js +5 -1
- package/dist/core/logging/logging.service.js +9 -5
- package/dist/core/logging/scoped-logger.js +5 -1
- package/dist/core/moleculer/agent-readiness-pull.js +4 -1
- package/dist/core/moleculer/agent-registration-request.js +7 -3
- package/dist/core/moleculer/cap-call-fn.js +7 -4
- package/dist/core/moleculer/cap-route-authority.js +8 -3
- package/dist/core/moleculer/hub-mesh-guard.js +9 -5
- package/dist/core/moleculer/moleculer.service.js +86 -79
- package/dist/core/network/network-quality.service.js +6 -2
- package/dist/core/notification/notification-wrapper.service.js +7 -3
- package/dist/core/notification/toast-wrapper.service.js +7 -3
- package/dist/core/provider/provider.tokens.js +4 -1
- package/dist/core/repl/repl-engine.service.js +8 -4
- package/dist/core/runner-health/runner-boot-check.js +15 -7
- package/dist/core/runner-health/update-preflight.js +14 -9
- package/dist/core/server-update/server-update.service.js +49 -12
- package/dist/core/server-update/system-apply-closure-patches.js +42 -6
- package/dist/core/server-update/system-ensure-prebuilds.js +6 -3
- package/dist/core/server-update/system-exec-npm.js +5 -2
- package/dist/core/storage/fs-storage-backend.js +5 -1
- package/dist/core/storage/storage-location-manager.js +5 -1
- package/dist/core/storage/storage.service.js +6 -2
- package/dist/core/streaming/ffmpeg-stream-info.js +8 -3
- package/dist/core/streaming/stream-probe.service.js +16 -12
- package/dist/core/streaming/ttl-cache.js +5 -1
- package/dist/core/topology/topology-emitter.service.js +23 -19
- package/dist/core/update-availability-emitter.js +7 -3
- package/dist/core/update-availability-store.js +45 -8
- package/dist/core/updates/agent-installed-packages.js +9 -5
- package/dist/core/updates/restart-marker.js +8 -3
- package/dist/core/updates/update-check-scheduler.js +18 -13
- package/dist/core/updates/wrapper-update-checker.js +7 -3
- package/dist/first-boot-addon-plan.js +6 -2
- package/dist/framework-nodepath.js +38 -2
- package/dist/i18n/request-lang.js +11 -7
- package/dist/launcher.js +65 -30
- package/dist/lifecycle-journal-path.js +38 -2
- package/dist/main.js +324 -286
- package/dist/manual-boot.js +156 -117
- package/dist/node-role.js +4 -1
- package/dist/package-inventory.js +48 -7
- package/dist/pending-restore.js +43 -7
- package/dist/single-copy-cleanup-runner.js +45 -9
- package/dist/single-copy-cleanup.js +15 -7
- package/dist/sqlite-restore.js +48 -9
- package/dist/starter.js +39 -4
- package/dist/ui-serving/lazy-ui-serving.js +39 -3
- package/package.json +7 -7
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Agent HTTP auth — pure request-authorization helpers for the agent's
|
|
3
4
|
* port-4444 API (mirrors the hub's /health hardening).
|
|
@@ -14,9 +15,20 @@
|
|
|
14
15
|
* agent made up, a proof the mesh CA signed), never by who calls. An
|
|
15
16
|
* unpaired agent offers nothing else remotely.
|
|
16
17
|
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.isLocalHostHeader = isLocalHostHeader;
|
|
20
|
+
exports.authInputOf = authInputOf;
|
|
21
|
+
exports.hasForwardingHeader = hasForwardingHeader;
|
|
22
|
+
exports.isGenuineLoopback = isGenuineLoopback;
|
|
23
|
+
exports.isLoopbackAddress = isLoopbackAddress;
|
|
24
|
+
exports.readBearerToken = readBearerToken;
|
|
25
|
+
exports.isAuthorizedAgentRequest = isAuthorizedAgentRequest;
|
|
26
|
+
exports.isPairingProtocolRequest = isPairingProtocolRequest;
|
|
27
|
+
exports.isUnlockSessionRequest = isUnlockSessionRequest;
|
|
28
|
+
exports.isUnlockInfoRequest = isUnlockInfoRequest;
|
|
17
29
|
const LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
18
30
|
/** `host[:port]` of the agent's own machine: localhost, 127.0.0.1 or [::1]. */
|
|
19
|
-
|
|
31
|
+
function isLocalHostHeader(host) {
|
|
20
32
|
const lower = host.trim().toLowerCase();
|
|
21
33
|
const name = lower.startsWith('[') ? lower.slice(0, lower.indexOf(']') + 1) : lower.split(':')[0];
|
|
22
34
|
return name !== undefined && LOCAL_HOSTNAMES.has(name);
|
|
@@ -53,7 +65,7 @@ function isBrowserSafeLocal(input) {
|
|
|
53
65
|
return true;
|
|
54
66
|
}
|
|
55
67
|
/** Build the auth input of a Node/Fastify request. */
|
|
56
|
-
|
|
68
|
+
function authInputOf(req) {
|
|
57
69
|
const one = (name) => {
|
|
58
70
|
const v = req.headers[name];
|
|
59
71
|
return typeof v === 'string' ? v : undefined;
|
|
@@ -79,18 +91,18 @@ const FORWARDING_HEADERS = [
|
|
|
79
91
|
'cf-connecting-ip',
|
|
80
92
|
];
|
|
81
93
|
/** True when any header says the request was relayed (D857): then loopback proves nothing. */
|
|
82
|
-
|
|
94
|
+
function hasForwardingHeader(headers) {
|
|
83
95
|
return FORWARDING_HEADERS.some((name) => headers[name] !== undefined);
|
|
84
96
|
}
|
|
85
97
|
/**
|
|
86
98
|
* A request from this machine itself: a loopback peer AND no forwarding header. A reverse proxy on
|
|
87
99
|
* the same host makes every caller look like 127.0.0.1; the header it adds is what gives it away.
|
|
88
100
|
*/
|
|
89
|
-
|
|
101
|
+
function isGenuineLoopback(input) {
|
|
90
102
|
return (input.forwarded !== true && isLoopbackAddress(input.remoteAddress) && isBrowserSafeLocal(input));
|
|
91
103
|
}
|
|
92
104
|
/** IPv4/IPv6 loopback (incl. the IPv4-mapped IPv6 form Node reports). */
|
|
93
|
-
|
|
105
|
+
function isLoopbackAddress(addr) {
|
|
94
106
|
if (!addr)
|
|
95
107
|
return false;
|
|
96
108
|
if (addr === '::1')
|
|
@@ -103,7 +115,7 @@ export function isLoopbackAddress(addr) {
|
|
|
103
115
|
return parts.every((p) => /^\d{1,3}$/.test(p));
|
|
104
116
|
}
|
|
105
117
|
/** Extract the bearer token value, or `null`. */
|
|
106
|
-
|
|
118
|
+
function readBearerToken(authorization) {
|
|
107
119
|
if (!authorization?.startsWith('Bearer '))
|
|
108
120
|
return null;
|
|
109
121
|
const token = authorization.slice('Bearer '.length);
|
|
@@ -113,7 +125,7 @@ export function readBearerToken(authorization) {
|
|
|
113
125
|
* True when the request may access the protected agent API: it comes from this
|
|
114
126
|
* machine, or it carries a session token minted from a hub unlock ticket.
|
|
115
127
|
*/
|
|
116
|
-
|
|
128
|
+
function isAuthorizedAgentRequest(input, sessionTokenOk = () => false) {
|
|
117
129
|
if (isGenuineLoopback(input))
|
|
118
130
|
return true;
|
|
119
131
|
const token = readBearerToken(input.authorization);
|
|
@@ -138,7 +150,7 @@ const PAIRING_POST = new Set([
|
|
|
138
150
|
* the network without a session. `forget` is NOT among them — leaving a hub is an
|
|
139
151
|
* authenticated action (this machine, or a hub-unlocked session).
|
|
140
152
|
*/
|
|
141
|
-
|
|
153
|
+
function isPairingProtocolRequest(method, urlPath) {
|
|
142
154
|
const pathOnly = urlPath.split('?')[0] ?? urlPath;
|
|
143
155
|
if (method === 'GET')
|
|
144
156
|
return PAIRING_GET.has(pathOnly);
|
|
@@ -150,7 +162,7 @@ export function isPairingProtocolRequest(method, urlPath) {
|
|
|
150
162
|
* Redeem a hub unlock ticket for a session token — reachable remotely without
|
|
151
163
|
* a prior session (the ticket IS the proof). Paired agents only.
|
|
152
164
|
*/
|
|
153
|
-
|
|
165
|
+
function isUnlockSessionRequest(method, urlPath) {
|
|
154
166
|
const pathOnly = urlPath.split('?')[0] ?? urlPath;
|
|
155
167
|
return method === 'POST' && pathOnly === '/api/agent/session';
|
|
156
168
|
}
|
|
@@ -158,7 +170,7 @@ export function isUnlockSessionRequest(method, urlPath) {
|
|
|
158
170
|
* Public unlock probe: `nodeId` + hub HTTPS origin for Continue-with-hub (D821).
|
|
159
171
|
* No secrets, no metrics — only what the locked unlock screen needs.
|
|
160
172
|
*/
|
|
161
|
-
|
|
173
|
+
function isUnlockInfoRequest(method, urlPath) {
|
|
162
174
|
const pathOnly = urlPath.split('?')[0] ?? urlPath;
|
|
163
175
|
return method === 'GET' && pathOnly === '/api/agent/unlock-info';
|
|
164
176
|
}
|
package/dist/agent/agent-http.js
CHANGED
|
@@ -1,30 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Agent HTTP server -- lightweight Fastify instance for agent status,
|
|
3
4
|
* process management, config editing, and static UI serving.
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.pickIpv4 = void 0;
|
|
44
|
+
exports.describePairedHub = describePairedHub;
|
|
45
|
+
exports.compareVersions = compareVersions;
|
|
46
|
+
exports.readUiDistCandidate = readUiDistCandidate;
|
|
47
|
+
exports.pickUiDist = pickUiDist;
|
|
48
|
+
exports.resolveUiDistDir = resolveUiDistDir;
|
|
49
|
+
exports.getRegistryNodes = getRegistryNodes;
|
|
50
|
+
exports.resolveHubEndpoint = resolveHubEndpoint;
|
|
51
|
+
exports.isOpaqueHostname = isOpaqueHostname;
|
|
52
|
+
exports.nodeDisplayName = nodeDisplayName;
|
|
53
|
+
exports.mapDiscoveredNodes = mapDiscoveredNodes;
|
|
54
|
+
exports.createAgentHttpServer = createAgentHttpServer;
|
|
55
|
+
exports.startAgentHttpServer = startAgentHttpServer;
|
|
56
|
+
const node_crypto_1 = require("node:crypto");
|
|
57
|
+
const fs = __importStar(require("node:fs"));
|
|
58
|
+
const path = __importStar(require("node:path"));
|
|
59
|
+
const fastify_1 = __importDefault(require("fastify"));
|
|
60
|
+
const zod_1 = require("zod");
|
|
61
|
+
const system_1 = require("@camstack/system");
|
|
62
|
+
const agent_sniffing_listener_js_1 = require("./agent-sniffing-listener.js");
|
|
63
|
+
const agent_http_auth_js_1 = require("./agent-http-auth.js");
|
|
64
|
+
const agent_pairing_routes_js_1 = require("./agent-pairing-routes.js");
|
|
65
|
+
const agent_pairing_store_js_1 = require("./agent-pairing-store.js");
|
|
66
|
+
const node_1 = require("@camstack/types/node");
|
|
67
|
+
const agent_update_routes_js_1 = require("./agent-update-routes.js");
|
|
68
|
+
const derive_hub_url_js_1 = require("./derive-hub-url.js");
|
|
69
|
+
Object.defineProperty(exports, "pickIpv4", { enumerable: true, get: function () { return derive_hub_url_js_1.pickIpv4; } });
|
|
70
|
+
const agent_addon_runtime_js_1 = require("./agent-addon-runtime.js");
|
|
71
|
+
const hubs_found_js_1 = require("./hubs-found.js");
|
|
20
72
|
/** The pinned CA's fingerprint, or `null` when none is pinned or the PEM cannot be read. */
|
|
21
|
-
|
|
73
|
+
function describePairedHub(pinnedCa, hubHttpsOrigin) {
|
|
22
74
|
if (pinnedCa === null)
|
|
23
75
|
return null;
|
|
24
76
|
try {
|
|
25
77
|
return {
|
|
26
78
|
url: hubHttpsOrigin,
|
|
27
|
-
caFingerprint: caFingerprintCompact(pinnedCa),
|
|
79
|
+
caFingerprint: (0, system_1.caFingerprintCompact)(pinnedCa),
|
|
28
80
|
};
|
|
29
81
|
}
|
|
30
82
|
catch {
|
|
@@ -32,7 +84,7 @@ export function describePairedHub(pinnedCa, hubHttpsOrigin) {
|
|
|
32
84
|
}
|
|
33
85
|
}
|
|
34
86
|
/** Dotted-numeric version compare; `null` sorts lowest. */
|
|
35
|
-
|
|
87
|
+
function compareVersions(a, b) {
|
|
36
88
|
if (a === null && b === null)
|
|
37
89
|
return 0;
|
|
38
90
|
if (a === null)
|
|
@@ -53,7 +105,7 @@ export function compareVersions(a, b) {
|
|
|
53
105
|
* Read an agent-ui package dir (`<base>/package.json` + `<base>/dist/index.html`)
|
|
54
106
|
* into a candidate. Returns `null` when the dist is absent/unusable.
|
|
55
107
|
*/
|
|
56
|
-
|
|
108
|
+
function readUiDistCandidate(baseDir) {
|
|
57
109
|
const dir = path.join(baseDir, 'dist');
|
|
58
110
|
if (!fs.existsSync(path.join(dir, 'index.html')))
|
|
59
111
|
return null;
|
|
@@ -83,13 +135,13 @@ export function readUiDistCandidate(baseDir) {
|
|
|
83
135
|
* over `@fastify/static` — so which dir that variable names is load-bearing
|
|
84
136
|
* here, not just at first boot.
|
|
85
137
|
*/
|
|
86
|
-
|
|
138
|
+
function pickUiDist(installed, bundled) {
|
|
87
139
|
if (installed && bundled) {
|
|
88
140
|
return compareVersions(bundled.version, installed.version) > 0 ? bundled.dir : installed.dir;
|
|
89
141
|
}
|
|
90
142
|
return installed?.dir ?? bundled?.dir ?? null;
|
|
91
143
|
}
|
|
92
|
-
|
|
144
|
+
function resolveUiDistDir(dataDir,
|
|
93
145
|
// `CAMSTACK_BUNDLED_ADDONS_DIR` — a dir of package dirs keyed by SHORT name
|
|
94
146
|
// (`<dir>/addon-agent-ui`), the same shape `AddonInstaller.findLocalPackage`
|
|
95
147
|
// joins onto. On a packaged desktop that is the closure's own scope dir,
|
|
@@ -127,10 +179,10 @@ function readConfigFile(configPath) {
|
|
|
127
179
|
}
|
|
128
180
|
/** agent.json holds the agent's private mesh key (D857): owner-only on every OS. */
|
|
129
181
|
function writeConfigFile(configPath, data) {
|
|
130
|
-
writeOwnerOnlyFileSync(configPath, JSON.stringify(data, null, 2));
|
|
182
|
+
(0, node_1.writeOwnerOnlyFileSync)(configPath, JSON.stringify(data, null, 2));
|
|
131
183
|
}
|
|
132
184
|
/** Live Moleculer registry snapshot — reused by agent-bootstrap's Option A. */
|
|
133
|
-
|
|
185
|
+
function getRegistryNodes(broker) {
|
|
134
186
|
try {
|
|
135
187
|
return broker.registry.getNodeList({ onlyAvailable: true }).map((node) => ({
|
|
136
188
|
id: node.id,
|
|
@@ -142,33 +194,30 @@ export function getRegistryNodes(broker) {
|
|
|
142
194
|
return [];
|
|
143
195
|
}
|
|
144
196
|
}
|
|
145
|
-
// `pickIpv4` moved to derive-hub-url.ts (single home shared with
|
|
146
|
-
// `deriveHubUrlFromRegistry`); re-exported here to preserve this module's API.
|
|
147
|
-
export { pickIpv4 };
|
|
148
197
|
/**
|
|
149
198
|
* A human-readable, reachable address for the hub node as the agent actually
|
|
150
199
|
* sees it in the Moleculer registry. Used to fill in the effective address
|
|
151
200
|
* even in UDP-discovery mode where no address was manually configured.
|
|
152
201
|
*/
|
|
153
|
-
|
|
202
|
+
function resolveHubEndpoint(nodes) {
|
|
154
203
|
const hub = nodes.find((n) => n.id === 'hub');
|
|
155
204
|
if (!hub)
|
|
156
205
|
return null;
|
|
157
|
-
return pickIpv4(hub.ipList) ?? hub.hostname ?? null;
|
|
206
|
+
return (0, derive_hub_url_js_1.pickIpv4)(hub.ipList) ?? hub.hostname ?? null;
|
|
158
207
|
}
|
|
159
208
|
/** A container id (12 hex) or full id (64 hex): a name nobody chose. */
|
|
160
|
-
|
|
209
|
+
function isOpaqueHostname(hostname) {
|
|
161
210
|
return /^[0-9a-f]{12}$|^[0-9a-f]{64}$/.test(hostname);
|
|
162
211
|
}
|
|
163
212
|
/**
|
|
164
213
|
* Prefer a name an operator can recognise over the bare Moleculer node id —
|
|
165
214
|
* and over a container's id, which is what the hostname of a hub in Docker is.
|
|
166
215
|
*/
|
|
167
|
-
|
|
216
|
+
function nodeDisplayName(node) {
|
|
168
217
|
const hostname = typeof node.hostname === 'string' ? node.hostname.trim() : '';
|
|
169
218
|
if (hostname.length > 0 && hostname !== node.id && !isOpaqueHostname(hostname))
|
|
170
219
|
return hostname;
|
|
171
|
-
const ip = pickIpv4(node.ipList);
|
|
220
|
+
const ip = (0, derive_hub_url_js_1.pickIpv4)(node.ipList);
|
|
172
221
|
if (ip !== null)
|
|
173
222
|
return ip;
|
|
174
223
|
return hostname.length > 0 ? hostname : node.id;
|
|
@@ -177,7 +226,7 @@ export function nodeDisplayName(node) {
|
|
|
177
226
|
* Map raw registry nodes (minus self) to the UI-facing shape: the hub carries
|
|
178
227
|
* a human `displayName` (hostname or IPv4) so the UI never shows only `hub`.
|
|
179
228
|
*/
|
|
180
|
-
|
|
229
|
+
function mapDiscoveredNodes(nodes, selfId) {
|
|
181
230
|
return nodes
|
|
182
231
|
.filter((n) => n.id !== selfId)
|
|
183
232
|
.map((n) => {
|
|
@@ -214,7 +263,7 @@ function getEffectiveConfig(configPath, nodeId) {
|
|
|
214
263
|
return {
|
|
215
264
|
name: typeof raw.name === 'string' ? raw.name : nodeId,
|
|
216
265
|
hubAddress: typeof raw.hubAddress === 'string' ? raw.hubAddress : null,
|
|
217
|
-
paired: isAgentPaired(configPath),
|
|
266
|
+
paired: (0, agent_pairing_store_js_1.isAgentPaired)(configPath),
|
|
218
267
|
hasMeshTls: raw.meshTls !== null && typeof raw.meshTls === 'object',
|
|
219
268
|
};
|
|
220
269
|
}
|
|
@@ -225,18 +274,18 @@ function getEffectiveConfig(configPath, nodeId) {
|
|
|
225
274
|
*/
|
|
226
275
|
const EDITABLE_CONFIG_KEYS = ['name', 'hubAddress', 'logLevel'];
|
|
227
276
|
/** Value types of the editable keys; unknown keys pass through to the allow-list refusal above. */
|
|
228
|
-
const ConfigPatchSchema = z.looseObject({
|
|
229
|
-
name: z.string().max(100).nullable().optional(),
|
|
230
|
-
hubAddress: z.string().max(300).nullable().optional(),
|
|
231
|
-
logLevel: z.enum(['debug', 'info', 'warn', 'error']).optional(),
|
|
277
|
+
const ConfigPatchSchema = zod_1.z.looseObject({
|
|
278
|
+
name: zod_1.z.string().max(100).nullable().optional(),
|
|
279
|
+
hubAddress: zod_1.z.string().max(300).nullable().optional(),
|
|
280
|
+
logLevel: zod_1.z.enum(['debug', 'info', 'warn', 'error']).optional(),
|
|
232
281
|
});
|
|
233
282
|
/** Clock skew allowed between the hub that issued a ticket and this agent's boot instant. */
|
|
234
283
|
const TICKET_BOOT_SKEW_MS = 2 * 60_000;
|
|
235
284
|
// ---------------------------------------------------------------------------
|
|
236
285
|
// Factory
|
|
237
286
|
// ---------------------------------------------------------------------------
|
|
238
|
-
|
|
239
|
-
const app =
|
|
287
|
+
async function createAgentHttpServer(getBroker, config) {
|
|
288
|
+
const app = (0, fastify_1.default)({ logger: false });
|
|
240
289
|
// No CORS: the agent's page is served by the agent itself, so every legitimate caller is
|
|
241
290
|
// same-origin. `Access-Control-Allow-Origin: *` would let any web page read this API (D857).
|
|
242
291
|
// -- Auth gate (port-4444 hardening, mirrors the hub's /health work) --
|
|
@@ -251,13 +300,13 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
251
300
|
* ends every session (D857).
|
|
252
301
|
*/
|
|
253
302
|
const unlockSessions = new Map();
|
|
254
|
-
let unlockJtis = new UnlockTicketJtiStore();
|
|
303
|
+
let unlockJtis = new system_1.UnlockTicketJtiStore();
|
|
255
304
|
let jtiBinding = null;
|
|
256
305
|
const bootMs = Date.now();
|
|
257
306
|
/** What vouches for a session now: the pinned CA, else nothing. */
|
|
258
307
|
const caBinding = () => {
|
|
259
|
-
const ca = pinnedMeshCaCert(config.configPath);
|
|
260
|
-
return ca === null ? null : `ca:${caFingerprintCompact(ca)}`;
|
|
308
|
+
const ca = (0, agent_pairing_store_js_1.pinnedMeshCaCert)(config.configPath);
|
|
309
|
+
return ca === null ? null : `ca:${(0, system_1.caFingerprintCompact)(ca)}`;
|
|
261
310
|
};
|
|
262
311
|
const sessionOk = (token) => {
|
|
263
312
|
const entry = unlockSessions.get(token);
|
|
@@ -286,19 +335,19 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
286
335
|
const matched = req.routeOptions.url ?? '';
|
|
287
336
|
if (method === 'GET' && matched === '/health')
|
|
288
337
|
return;
|
|
289
|
-
if (isPairingProtocolRequest(method, matched))
|
|
338
|
+
if ((0, agent_http_auth_js_1.isPairingProtocolRequest)(method, matched))
|
|
290
339
|
return;
|
|
291
|
-
if (isUnlockSessionRequest(method, matched))
|
|
340
|
+
if ((0, agent_http_auth_js_1.isUnlockSessionRequest)(method, matched))
|
|
292
341
|
return;
|
|
293
|
-
if (isUnlockInfoRequest(method, matched))
|
|
342
|
+
if ((0, agent_http_auth_js_1.isUnlockInfoRequest)(method, matched))
|
|
294
343
|
return;
|
|
295
|
-
const authInput = authInputOf(req);
|
|
296
|
-
if (isAuthorizedAgentRequest(authInput, sessionOk))
|
|
344
|
+
const authInput = (0, agent_http_auth_js_1.authInputOf)(req);
|
|
345
|
+
if ((0, agent_http_auth_js_1.isAuthorizedAgentRequest)(authInput, sessionOk))
|
|
297
346
|
return;
|
|
298
347
|
return reply.status(401).send({ ok: false, error: 'unauthorized' });
|
|
299
348
|
});
|
|
300
349
|
if (config.pairing !== undefined) {
|
|
301
|
-
registerAgentPairingRoutes(app, {
|
|
350
|
+
(0, agent_pairing_routes_js_1.registerAgentPairingRoutes)(app, {
|
|
302
351
|
pairing: config.pairing,
|
|
303
352
|
onForgetHub: config.onForgetHub ?? (async () => undefined),
|
|
304
353
|
log: (message) => config.log?.info(message),
|
|
@@ -353,15 +402,15 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
353
402
|
// where `eff.hubAddress` is null.
|
|
354
403
|
const resolvedHubAddress = resolveHubEndpoint(nodes);
|
|
355
404
|
// HTTPS origin the agent UI uses for "Continue with hub" unlock (D821).
|
|
356
|
-
const hubHttpsOrigin = (eff.hubAddress !== null ? deriveHubUrlFromHubAddress(eff.hubAddress) : undefined) ??
|
|
357
|
-
(resolvedHubAddress !== null ? deriveHubUrlFromHubAddress(resolvedHubAddress) : undefined) ??
|
|
405
|
+
const hubHttpsOrigin = (eff.hubAddress !== null ? (0, derive_hub_url_js_1.deriveHubUrlFromHubAddress)(eff.hubAddress) : undefined) ??
|
|
406
|
+
(resolvedHubAddress !== null ? (0, derive_hub_url_js_1.deriveHubUrlFromHubAddress)(resolvedHubAddress) : undefined) ??
|
|
358
407
|
null;
|
|
359
408
|
// Version of the Electron wrapper (injected by the desktop app); absent
|
|
360
409
|
// when the agent runs headless / in Docker.
|
|
361
410
|
const appVersion = process.env['CAMSTACK_AGENT_APP_VERSION'] ?? null;
|
|
362
411
|
const discoveredNodes = mapDiscoveredNodes(nodes, broker.nodeID);
|
|
363
412
|
// The hub this agent is paired with, for the agent UI's "Paired with" card (D857).
|
|
364
|
-
const pairedHub = describePairedHub(pinnedMeshCaCert(config.configPath), hubHttpsOrigin);
|
|
413
|
+
const pairedHub = describePairedHub((0, agent_pairing_store_js_1.pinnedMeshCaCert)(config.configPath), hubHttpsOrigin);
|
|
365
414
|
try {
|
|
366
415
|
const status = (await broker.call('$agent.status'));
|
|
367
416
|
return {
|
|
@@ -403,8 +452,8 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
403
452
|
const eff = getEffectiveConfig(config.configPath, config.nodeId);
|
|
404
453
|
const nodes = getRegistryNodes(getBroker());
|
|
405
454
|
const resolvedHubAddress = resolveHubEndpoint(nodes);
|
|
406
|
-
const hubHttpsOrigin = (eff.hubAddress !== null ? deriveHubUrlFromHubAddress(eff.hubAddress) : undefined) ??
|
|
407
|
-
(resolvedHubAddress !== null ? deriveHubUrlFromHubAddress(resolvedHubAddress) : undefined) ??
|
|
455
|
+
const hubHttpsOrigin = (eff.hubAddress !== null ? (0, derive_hub_url_js_1.deriveHubUrlFromHubAddress)(eff.hubAddress) : undefined) ??
|
|
456
|
+
(resolvedHubAddress !== null ? (0, derive_hub_url_js_1.deriveHubUrlFromHubAddress)(resolvedHubAddress) : undefined) ??
|
|
408
457
|
null;
|
|
409
458
|
return {
|
|
410
459
|
paired: eff.paired,
|
|
@@ -415,7 +464,7 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
415
464
|
// -- Unlock session (hub admin ticket → tab Bearer; D821) -----------
|
|
416
465
|
app.post('/api/agent/session', async (req, reply) => {
|
|
417
466
|
// The ticket is signed by the mesh CA this agent pinned at pairing (D857).
|
|
418
|
-
const pinnedCa = pinnedMeshCaCert(config.configPath);
|
|
467
|
+
const pinnedCa = (0, agent_pairing_store_js_1.pinnedMeshCaCert)(config.configPath);
|
|
419
468
|
if (pinnedCa === null) {
|
|
420
469
|
return reply.status(400).send({ ok: false, error: 'agent is not paired' });
|
|
421
470
|
}
|
|
@@ -424,7 +473,7 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
424
473
|
return reply.status(400).send({ ok: false, error: 'ticket required' });
|
|
425
474
|
}
|
|
426
475
|
// Nothing issued before this process started is accepted: the one-use ledger is in memory.
|
|
427
|
-
const payload = verifyAgentUiUnlockTicket(pinnedCa, ticket, {
|
|
476
|
+
const payload = (0, system_1.verifyAgentUiUnlockTicket)(pinnedCa, ticket, {
|
|
428
477
|
expectedNodeId: config.nodeId,
|
|
429
478
|
notBeforeMs: bootMs - TICKET_BOOT_SKEW_MS,
|
|
430
479
|
});
|
|
@@ -434,13 +483,13 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
434
483
|
}
|
|
435
484
|
// A new vouching CA or secret starts a new ledger.
|
|
436
485
|
if (jtiBinding !== binding) {
|
|
437
|
-
unlockJtis = new UnlockTicketJtiStore();
|
|
486
|
+
unlockJtis = new system_1.UnlockTicketJtiStore();
|
|
438
487
|
jtiBinding = binding;
|
|
439
488
|
}
|
|
440
489
|
if (!unlockJtis.consume(payload.jti, payload.exp)) {
|
|
441
490
|
return reply.status(401).send({ ok: false, error: 'unlock ticket already used' });
|
|
442
491
|
}
|
|
443
|
-
const token = randomBytes(32).toString('base64url');
|
|
492
|
+
const token = (0, node_crypto_1.randomBytes)(32).toString('base64url');
|
|
444
493
|
// Session outlives the ticket so the tab keeps working after redeem.
|
|
445
494
|
const sessionExp = Date.now() + 8 * 60 * 60_000;
|
|
446
495
|
unlockSessions.set(token, { exp: sessionExp, binding });
|
|
@@ -462,7 +511,7 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
462
511
|
broker.call('$agent.status').catch(() => null),
|
|
463
512
|
broker.call('$process.list').catch(() => []),
|
|
464
513
|
]);
|
|
465
|
-
return joinAddonRuntime(addonsFromStatus(status), processesFromList(list));
|
|
514
|
+
return (0, agent_addon_runtime_js_1.joinAddonRuntime)((0, agent_addon_runtime_js_1.addonsFromStatus)(status), (0, agent_addon_runtime_js_1.processesFromList)(list));
|
|
466
515
|
});
|
|
467
516
|
// -- Addon restart --------------------------------------------------
|
|
468
517
|
app.post('/api/agent/addon/restart', async (req, reply) => {
|
|
@@ -543,13 +592,13 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
543
592
|
// -- Updates (framework local; addon roster read-only) --------------
|
|
544
593
|
// Registered AFTER the onRequest hook above, so every path it mounts is
|
|
545
594
|
// gated by the same loopback-or-bearer rule as the rest of `/api/`.
|
|
546
|
-
registerAgentUpdateRoutes(app, config.updateControls ?? {});
|
|
595
|
+
(0, agent_update_routes_js_1.registerAgentUpdateRoutes)(app, config.updateControls ?? {});
|
|
547
596
|
// -- Hubs found on this network (D839) ------------------------------
|
|
548
597
|
// The cached list is free; the refresh browses mDNS for a few seconds. The
|
|
549
598
|
// UI asks on demand (opening the edit form, "Search again"), never on its
|
|
550
599
|
// status poll.
|
|
551
600
|
const hubsFinder = config.hubsFinder ??
|
|
552
|
-
createHubsFinder({
|
|
601
|
+
(0, hubs_found_js_1.createHubsFinder)({
|
|
553
602
|
getConfiguredHubAddress: () => getEffectiveConfig(config.configPath, config.nodeId).hubAddress,
|
|
554
603
|
log: (message) => console.warn(`[Agent] ${message}`),
|
|
555
604
|
});
|
|
@@ -564,7 +613,7 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
564
613
|
// -- Static file serving (agent-ui) ---------------------------------
|
|
565
614
|
const uiDir = resolveUiDistDir(config.dataDir, process.env['CAMSTACK_BUNDLED_ADDONS_DIR']);
|
|
566
615
|
if (uiDir) {
|
|
567
|
-
const fastifyStatic = await
|
|
616
|
+
const fastifyStatic = await Promise.resolve().then(() => __importStar(require('@fastify/static')));
|
|
568
617
|
// Every route the static plugin mounts is the public UI bundle: tag them for the auth gate.
|
|
569
618
|
let mountingAssets = true;
|
|
570
619
|
app.addHook('onRoute', (route) => {
|
|
@@ -607,14 +656,14 @@ export async function createAgentHttpServer(getBroker, config) {
|
|
|
607
656
|
* of a connection picks the protocol, so there is no second port. Resolves with
|
|
608
657
|
* the listener (to hot-swap the certificate), or `null` when it failed to start.
|
|
609
658
|
*/
|
|
610
|
-
|
|
659
|
+
async function startAgentHttpServer(getBroker, config) {
|
|
611
660
|
try {
|
|
612
661
|
const app = await createAgentHttpServer(getBroker, config);
|
|
613
662
|
await app.ready();
|
|
614
|
-
const material = loadAgentHttps(config.dataDir, (reason) => config.log?.error('The HTTPS bundle on disk is unusable - serving plain HTTP only', {
|
|
663
|
+
const material = (0, system_1.loadAgentHttps)(config.dataDir, (reason) => config.log?.error('The HTTPS bundle on disk is unusable - serving plain HTTP only', {
|
|
615
664
|
meta: { reason },
|
|
616
665
|
}));
|
|
617
|
-
const listener = await startSniffingListener({
|
|
666
|
+
const listener = await (0, agent_sniffing_listener_js_1.startSniffingListener)({
|
|
618
667
|
httpServer: app.server,
|
|
619
668
|
port: config.port,
|
|
620
669
|
host: '0.0.0.0',
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HUB_UPDATE_TIMEOUT_MS = exports.HUB_ADDON_UPDATE_ACTION = exports.HUB_ADDON_LIST_ACTION = void 0;
|
|
4
|
+
exports.hubVersionsFromList = hubVersionsFromList;
|
|
5
|
+
exports.isBehindHub = isBehindHub;
|
|
6
|
+
exports.createAgentHubAddonControls = createAgentHubAddonControls;
|
|
1
7
|
/**
|
|
2
8
|
* Updating an addon from the agent itself (D840) — by asking the HUB.
|
|
3
9
|
*
|
|
@@ -22,18 +28,18 @@
|
|
|
22
28
|
* (`remote-addon-update-grant.ts`): own node, the hub's recorded version, audited.
|
|
23
29
|
* Any refusal reaches the UI verbatim as the update's failure, never as silence.
|
|
24
30
|
*/
|
|
25
|
-
|
|
31
|
+
const index_js_1 = require("../server-root/index.js");
|
|
26
32
|
/** Hub procedures this module calls, as `$core-caps` actions. */
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
exports.HUB_ADDON_LIST_ACTION = '$core-caps.addons.list';
|
|
34
|
+
exports.HUB_ADDON_UPDATE_ACTION = '$core-caps.addons.updatePackage';
|
|
29
35
|
/** An agent's deploy + reload of a large package can take minutes. */
|
|
30
|
-
|
|
36
|
+
exports.HUB_UPDATE_TIMEOUT_MS = 330_000;
|
|
31
37
|
const HUB_LIST_TIMEOUT_MS = 15_000;
|
|
32
38
|
function errorMessage(err) {
|
|
33
39
|
return err instanceof Error ? err.message : String(err);
|
|
34
40
|
}
|
|
35
41
|
/** `packageName → packageVersion` from an `addons.list` answer; unreadable rows are skipped. */
|
|
36
|
-
|
|
42
|
+
function hubVersionsFromList(list) {
|
|
37
43
|
const out = new Map();
|
|
38
44
|
if (!Array.isArray(list))
|
|
39
45
|
return out;
|
|
@@ -52,8 +58,8 @@ export function hubVersionsFromList(list) {
|
|
|
52
58
|
return out;
|
|
53
59
|
}
|
|
54
60
|
/** True when the hub's version is strictly newer than this node's. */
|
|
55
|
-
|
|
56
|
-
return installed !== null && hub !== null && compareSemver(hub, installed) > 0;
|
|
61
|
+
function isBehindHub(installed, hub) {
|
|
62
|
+
return installed !== null && hub !== null && (0, index_js_1.compareSemver)(hub, installed) > 0;
|
|
57
63
|
}
|
|
58
64
|
/** The hub answered `{ success: false, error }`, or something unreadable. */
|
|
59
65
|
function failureOf(result) {
|
|
@@ -64,11 +70,11 @@ function failureOf(result) {
|
|
|
64
70
|
const error = Reflect.get(result, 'error');
|
|
65
71
|
return typeof error === 'string' && error.length > 0 ? error : 'the hub reported a failure';
|
|
66
72
|
}
|
|
67
|
-
|
|
73
|
+
function createAgentHubAddonControls(deps) {
|
|
68
74
|
const states = new Map();
|
|
69
75
|
const getHubVersions = async () => {
|
|
70
76
|
try {
|
|
71
|
-
const list = await deps.callHub(HUB_ADDON_LIST_ACTION, undefined, HUB_LIST_TIMEOUT_MS);
|
|
77
|
+
const list = await deps.callHub(exports.HUB_ADDON_LIST_ACTION, undefined, HUB_LIST_TIMEOUT_MS);
|
|
72
78
|
return { ok: true, versions: hubVersionsFromList(list) };
|
|
73
79
|
}
|
|
74
80
|
catch (err) {
|
|
@@ -77,7 +83,7 @@ export function createAgentHubAddonControls(deps) {
|
|
|
77
83
|
};
|
|
78
84
|
const run = async (packageName, version) => {
|
|
79
85
|
try {
|
|
80
|
-
const result = await deps.callHub(HUB_ADDON_UPDATE_ACTION, { name: packageName, version, nodeId: deps.nodeId }, HUB_UPDATE_TIMEOUT_MS);
|
|
86
|
+
const result = await deps.callHub(exports.HUB_ADDON_UPDATE_ACTION, { name: packageName, version, nodeId: deps.nodeId }, exports.HUB_UPDATE_TIMEOUT_MS);
|
|
81
87
|
const failure = failureOf(result);
|
|
82
88
|
states.set(packageName, failure === null
|
|
83
89
|
? { status: 'done', targetVersion: version, message: null }
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAgentHubRegistration = createAgentHubRegistration;
|
|
1
4
|
/**
|
|
2
5
|
* The agent's upward capability registration (D3).
|
|
3
6
|
*
|
|
@@ -25,8 +28,8 @@
|
|
|
25
28
|
* coalesced (one in flight, at most one queued, the manifest built when it
|
|
26
29
|
* goes). Nothing waits on a timer: the triggers are events, the retry is the ack.
|
|
27
30
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
const system_1 = require("@camstack/system");
|
|
32
|
+
function createAgentHubRegistration(opts) {
|
|
30
33
|
let sending = false;
|
|
31
34
|
let queuedReason = null;
|
|
32
35
|
const send = (reason) => {
|
|
@@ -38,12 +41,12 @@ export function createAgentHubRegistration(opts) {
|
|
|
38
41
|
const broker = {
|
|
39
42
|
call: (action, params, callOpts) => opts.broker().call(action, params, callOpts),
|
|
40
43
|
};
|
|
41
|
-
callRegisterNodeWithRetry(broker, manifest, {
|
|
44
|
+
(0, system_1.callRegisterNodeWithRetry)(broker, manifest, {
|
|
42
45
|
target: 'hub',
|
|
43
46
|
...(opts.signal !== undefined ? { signal: opts.signal } : {}),
|
|
44
47
|
log: opts.log,
|
|
45
48
|
onAttemptFailed: (err) => {
|
|
46
|
-
if (meshErrorType(err) === MESH_NODE_UNAUTHENTICATED_TYPE)
|
|
49
|
+
if ((0, system_1.meshErrorType)(err) === system_1.MESH_NODE_UNAUTHENTICATED_TYPE)
|
|
47
50
|
opts.onCertificateRefused?.(err);
|
|
48
51
|
},
|
|
49
52
|
})
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AGENT_LOCAL_DATA_STORE_ENV = void 0;
|
|
4
|
+
exports.resolveAgentInfraCapabilities = resolveAgentInfraCapabilities;
|
|
1
5
|
/**
|
|
2
6
|
* Which infra capabilities an AGENT boots — and the one it no longer does.
|
|
3
7
|
*
|
|
@@ -43,13 +47,13 @@
|
|
|
43
47
|
* in this series stay in place: commit 1 is inert whenever a local engine
|
|
44
48
|
* exists, and commit 3 is documentation.
|
|
45
49
|
*/
|
|
46
|
-
|
|
50
|
+
const system_1 = require("@camstack/system");
|
|
47
51
|
/**
|
|
48
52
|
* The env var that puts the local engine back. Named for what it restores, not
|
|
49
53
|
* for what it disables, so an operator reading a container's environment can
|
|
50
54
|
* tell what it does without this file.
|
|
51
55
|
*/
|
|
52
|
-
|
|
56
|
+
exports.AGENT_LOCAL_DATA_STORE_ENV = 'CAMSTACK_AGENT_LOCAL_DATA_STORE';
|
|
53
57
|
/** The capability an agent no longer boots. */
|
|
54
58
|
const DATA_STORE_PROVIDER = 'data-store-provider';
|
|
55
59
|
/**
|
|
@@ -87,7 +91,7 @@ function isEnabled(raw) {
|
|
|
87
91
|
*
|
|
88
92
|
* `INFRA_CAPABILITIES` itself is never touched: the hub reads the same array.
|
|
89
93
|
*/
|
|
90
|
-
|
|
91
|
-
const keepLocalStore = isEnabled(env[AGENT_LOCAL_DATA_STORE_ENV]);
|
|
92
|
-
return INFRA_CAPABILITIES.filter((cap) => !HUB_ONLY_INFRA.has(cap.name) && (keepLocalStore || cap.name !== DATA_STORE_PROVIDER));
|
|
94
|
+
function resolveAgentInfraCapabilities(env) {
|
|
95
|
+
const keepLocalStore = isEnabled(env[exports.AGENT_LOCAL_DATA_STORE_ENV]);
|
|
96
|
+
return system_1.INFRA_CAPABILITIES.filter((cap) => !HUB_ONLY_INFRA.has(cap.name) && (keepLocalStore || cap.name !== DATA_STORE_PROVIDER));
|
|
93
97
|
}
|