@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,5 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AddonPagesService = void 0;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
3
39
|
/**
|
|
4
40
|
* AddonPagesService — server-side helper that backs the static file
|
|
5
41
|
* route `/api/addon-pages/:addonId/*` (registered in `main.ts`).
|
|
@@ -17,7 +53,7 @@ import * as fs from 'node:fs';
|
|
|
17
53
|
* addons can't be probed via path traversal tricks) and on
|
|
18
54
|
* `ConfigService` to locate the addons directory.
|
|
19
55
|
*/
|
|
20
|
-
|
|
56
|
+
class AddonPagesService {
|
|
21
57
|
loggingService;
|
|
22
58
|
configService;
|
|
23
59
|
caps;
|
|
@@ -68,3 +104,4 @@ export class AddonPagesService {
|
|
|
68
104
|
return path.resolve(dataPath, 'addons');
|
|
69
105
|
}
|
|
70
106
|
}
|
|
107
|
+
exports.AddonPagesService = AddonPagesService;
|
|
@@ -1,5 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AddonWidgetsService = void 0;
|
|
37
|
+
exports.stripBundleVersionSegment = stripBundleVersionSegment;
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
3
40
|
/**
|
|
4
41
|
* Strip the `@<nodeId>` suffix the CapabilityBridge appends to
|
|
5
42
|
* collection-provider registry keys for cross-node addons. The widget
|
|
@@ -19,7 +56,7 @@ const VERSION_SEGMENT_RE = /^v[0-9a-f]{6,}$/;
|
|
|
19
56
|
* `{ filePath, versioned }` — `versioned` lets the route serve content-
|
|
20
57
|
* addressed files as `immutable`. Pure + exported for the spec.
|
|
21
58
|
*/
|
|
22
|
-
|
|
59
|
+
function stripBundleVersionSegment(rawPath) {
|
|
23
60
|
const slash = rawPath.indexOf('/');
|
|
24
61
|
if (slash > 0 && VERSION_SEGMENT_RE.test(rawPath.slice(0, slash))) {
|
|
25
62
|
return { filePath: rawPath.slice(slash + 1), versioned: true };
|
|
@@ -45,7 +82,7 @@ export function stripBundleVersionSegment(rawPath) {
|
|
|
45
82
|
* `dist/<entryId>/`) resolve to the right sub-folder instead of the
|
|
46
83
|
* pre-bundle `addons/@camstack/addon-<id>/dist/` layout.
|
|
47
84
|
*/
|
|
48
|
-
|
|
85
|
+
class AddonWidgetsService {
|
|
49
86
|
loggingService;
|
|
50
87
|
caps;
|
|
51
88
|
registry;
|
|
@@ -101,3 +138,4 @@ export class AddonWidgetsService {
|
|
|
101
138
|
return resolvedFile;
|
|
102
139
|
}
|
|
103
140
|
}
|
|
141
|
+
exports.AddonWidgetsService = AddonWidgetsService;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Node addon back-fill — converge a node to the addon roster THAT NODE last
|
|
3
4
|
* declared.
|
|
@@ -48,6 +49,12 @@
|
|
|
48
49
|
* This module is pure/seam-driven on purpose: the decision of what a node should
|
|
49
50
|
* have is asserted in unit tests with no Moleculer, filesystem or npm registry.
|
|
50
51
|
*/
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.BackfillAttemptTracker = exports.MAX_BACKFILL_ATTEMPTS = void 0;
|
|
54
|
+
exports.triggerMayDeliver = triggerMayDeliver;
|
|
55
|
+
exports.computeBackfillPlan = computeBackfillPlan;
|
|
56
|
+
exports.confirmBackfillPlan = confirmBackfillPlan;
|
|
57
|
+
exports.executeBackfill = executeBackfill;
|
|
51
58
|
/** Triggers permitted to install packages onto a node. */
|
|
52
59
|
const DELIVERING_TRIGGERS = new Set([
|
|
53
60
|
'node-registration',
|
|
@@ -55,14 +62,14 @@ const DELIVERING_TRIGGERS = new Set([
|
|
|
55
62
|
'operator-repair',
|
|
56
63
|
]);
|
|
57
64
|
/** Is this trigger allowed to put bytes on a node? */
|
|
58
|
-
|
|
65
|
+
function triggerMayDeliver(trigger) {
|
|
59
66
|
return DELIVERING_TRIGGERS.has(trigger);
|
|
60
67
|
}
|
|
61
68
|
/**
|
|
62
69
|
* Decide what a node is missing relative to its own last-declared roster.
|
|
63
70
|
* Pure — no I/O, no clock, no randomness.
|
|
64
71
|
*/
|
|
65
|
-
|
|
72
|
+
function computeBackfillPlan(input) {
|
|
66
73
|
const liveNames = new Set(input.live.map((p) => p.name));
|
|
67
74
|
const targets = [];
|
|
68
75
|
const retired = [];
|
|
@@ -87,7 +94,7 @@ export function computeBackfillPlan(input) {
|
|
|
87
94
|
}
|
|
88
95
|
return { targets, retired, notOnHub, liveCount: liveNames.size };
|
|
89
96
|
}
|
|
90
|
-
|
|
97
|
+
function confirmBackfillPlan(plan, secondRead) {
|
|
91
98
|
const present = new Set(secondRead.map((p) => p.name));
|
|
92
99
|
const targets = plan.targets.filter((t) => !present.has(t.name));
|
|
93
100
|
const contradicted = plan.targets.filter((t) => present.has(t.name));
|
|
@@ -98,7 +105,7 @@ export function confirmBackfillPlan(plan, secondRead) {
|
|
|
98
105
|
* Mirrors `CrashSupervisor.MAX_CRASHES_IN_WINDOW` in intent: bounded, terminal,
|
|
99
106
|
* loud — never an infinite retry loop.
|
|
100
107
|
*/
|
|
101
|
-
|
|
108
|
+
exports.MAX_BACKFILL_ATTEMPTS = 3;
|
|
102
109
|
/**
|
|
103
110
|
* Per-`(node, package)` delivery circuit breaker. In-memory and process-scoped
|
|
104
111
|
* on purpose: it bounds retries within one hub lifetime, and a hub restart is an
|
|
@@ -106,7 +113,7 @@ export const MAX_BACKFILL_ATTEMPTS = 3;
|
|
|
106
113
|
* `CrashSupervisor`). It stores no intent — the durable record of what a node
|
|
107
114
|
* should have lives in `ClusterNodeHistoryStore`, not here.
|
|
108
115
|
*/
|
|
109
|
-
|
|
116
|
+
class BackfillAttemptTracker {
|
|
110
117
|
failures = new Map();
|
|
111
118
|
forNode(nodeId) {
|
|
112
119
|
const existing = this.failures.get(nodeId);
|
|
@@ -123,7 +130,7 @@ export class BackfillAttemptTracker {
|
|
|
123
130
|
return new Set();
|
|
124
131
|
const retired = new Set();
|
|
125
132
|
for (const [name, state] of node) {
|
|
126
|
-
if (state.attempts >= MAX_BACKFILL_ATTEMPTS)
|
|
133
|
+
if (state.attempts >= exports.MAX_BACKFILL_ATTEMPTS)
|
|
127
134
|
retired.add(name);
|
|
128
135
|
}
|
|
129
136
|
return retired;
|
|
@@ -137,7 +144,7 @@ export class BackfillAttemptTracker {
|
|
|
137
144
|
name,
|
|
138
145
|
version: state.version,
|
|
139
146
|
attempts: state.attempts,
|
|
140
|
-
retired: state.attempts >= MAX_BACKFILL_ATTEMPTS,
|
|
147
|
+
retired: state.attempts >= exports.MAX_BACKFILL_ATTEMPTS,
|
|
141
148
|
lastError: state.lastError,
|
|
142
149
|
}));
|
|
143
150
|
}
|
|
@@ -147,7 +154,7 @@ export class BackfillAttemptTracker {
|
|
|
147
154
|
// A different hub version is a new fact — it earns a fresh set of attempts.
|
|
148
155
|
const attempts = prior && prior.version === version ? prior.attempts + 1 : 1;
|
|
149
156
|
node.set(name, { version, attempts, lastError: error });
|
|
150
|
-
return { attempts, retired: attempts >= MAX_BACKFILL_ATTEMPTS };
|
|
157
|
+
return { attempts, retired: attempts >= exports.MAX_BACKFILL_ATTEMPTS };
|
|
151
158
|
}
|
|
152
159
|
recordSuccess(nodeId, name) {
|
|
153
160
|
this.failures.get(nodeId)?.delete(name);
|
|
@@ -157,12 +164,13 @@ export class BackfillAttemptTracker {
|
|
|
157
164
|
this.failures.delete(nodeId);
|
|
158
165
|
}
|
|
159
166
|
}
|
|
167
|
+
exports.BackfillAttemptTracker = BackfillAttemptTracker;
|
|
160
168
|
/**
|
|
161
169
|
* Deliver every planned package, then reload the node ONCE. Per-package failures
|
|
162
170
|
* are isolated and counted — one broken package must not stop the others, and
|
|
163
171
|
* must not retry forever.
|
|
164
172
|
*/
|
|
165
|
-
|
|
173
|
+
async function executeBackfill(seam, nodeId, plan, tracker) {
|
|
166
174
|
const delivered = [];
|
|
167
175
|
const failed = [];
|
|
168
176
|
for (const target of plan.targets) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* "Is the hub currently writing addons to this node?"
|
|
3
4
|
*
|
|
@@ -33,6 +34,8 @@
|
|
|
33
34
|
* carrying nothing durable. Losing it on a restart is correct — a hub that just
|
|
34
35
|
* restarted has no delivery in flight.
|
|
35
36
|
*/
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.AgentDeliveryLedger = exports.DELIVERY_GRACE_MS = void 0;
|
|
36
39
|
/**
|
|
37
40
|
* How long after a delivery finishes the node stays protected from a back-fill.
|
|
38
41
|
*
|
|
@@ -41,8 +44,8 @@
|
|
|
41
44
|
* group runner — 12 on `little-unraid`) land over the following seconds. Each
|
|
42
45
|
* one fires a reconcile.
|
|
43
46
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
exports.DELIVERY_GRACE_MS = 60_000;
|
|
48
|
+
class AgentDeliveryLedger {
|
|
46
49
|
byNode = new Map();
|
|
47
50
|
forNode(nodeId) {
|
|
48
51
|
const existing = this.byNode.get(nodeId);
|
|
@@ -88,7 +91,7 @@ export class AgentDeliveryLedger {
|
|
|
88
91
|
if (!state)
|
|
89
92
|
return null;
|
|
90
93
|
const since = state.lastFinishedAt === 0 ? null : now - state.lastFinishedAt;
|
|
91
|
-
if (state.inFlight === 0 && (since === null || since >= DELIVERY_GRACE_MS)) {
|
|
94
|
+
if (state.inFlight === 0 && (since === null || since >= exports.DELIVERY_GRACE_MS)) {
|
|
92
95
|
// Window closed — drop the package memory so a later suppression names
|
|
93
96
|
// only the packages of the delivery that caused it.
|
|
94
97
|
state.packages.clear();
|
|
@@ -106,3 +109,4 @@ export class AgentDeliveryLedger {
|
|
|
106
109
|
this.byNode.delete(nodeId);
|
|
107
110
|
}
|
|
108
111
|
}
|
|
112
|
+
exports.AgentDeliveryLedger = AgentDeliveryLedger;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.agentOfflineData = agentOfflineData;
|
|
4
|
+
exports.nodeDisplayName = nodeDisplayName;
|
|
1
5
|
/**
|
|
2
6
|
* The payload of `agent.offline`, built from what Moleculer told us.
|
|
3
7
|
*
|
|
@@ -6,7 +10,7 @@
|
|
|
6
10
|
* DISCONNECT on a clean stop. The notification centre turns it into the body
|
|
7
11
|
* of the "node offline" notification (D820).
|
|
8
12
|
*/
|
|
9
|
-
|
|
13
|
+
function agentOfflineData(agentId, unexpected, nodeName) {
|
|
10
14
|
return {
|
|
11
15
|
agentId,
|
|
12
16
|
...(nodeName !== undefined ? { nodeName } : {}),
|
|
@@ -16,7 +20,7 @@ export function agentOfflineData(agentId, unexpected, nodeName) {
|
|
|
16
20
|
};
|
|
17
21
|
}
|
|
18
22
|
/** The history's display name for a node — only a real one, never the id echoed back. */
|
|
19
|
-
|
|
23
|
+
function nodeDisplayName(nodeId, history) {
|
|
20
24
|
const name = history?.find((row) => row.id === nodeId)?.name;
|
|
21
25
|
return name !== undefined && name.length > 0 && name !== nodeId ? name : undefined;
|
|
22
26
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertPairableHost = assertPairableHost;
|
|
4
|
+
exports.createHttpAgentPairingTransport = createHttpAgentPairingTransport;
|
|
1
5
|
/**
|
|
2
6
|
* The hub's HTTP client for an agent's pairing endpoints (D857).
|
|
3
7
|
*
|
|
@@ -11,61 +15,61 @@
|
|
|
11
15
|
* the operator's own network, never to a public address (the hub must not be a
|
|
12
16
|
* way to make requests to arbitrary hosts).
|
|
13
17
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
const node_net_1 = require("node:net");
|
|
19
|
+
const system_1 = require("@camstack/system");
|
|
20
|
+
const zod_1 = require("zod");
|
|
17
21
|
const REQUEST_TIMEOUT_MS = 8_000;
|
|
18
22
|
const MAX_RESPONSE_BYTES = 128 * 1024;
|
|
19
|
-
const HelloSchema = z.object({
|
|
20
|
-
protocol: z.number(),
|
|
21
|
-
nodeId: z.string().min(1).max(128),
|
|
22
|
-
version: z.string().nullable(),
|
|
23
|
-
state: z.enum(['unpaired', 'pending', 'paired']),
|
|
24
|
-
pendingExpiresAt: z.number().nullable(),
|
|
23
|
+
const HelloSchema = zod_1.z.object({
|
|
24
|
+
protocol: zod_1.z.number(),
|
|
25
|
+
nodeId: zod_1.z.string().min(1).max(128),
|
|
26
|
+
version: zod_1.z.string().nullable(),
|
|
27
|
+
state: zod_1.z.enum(['unpaired', 'pending', 'paired']),
|
|
28
|
+
pendingExpiresAt: zod_1.z.number().nullable(),
|
|
25
29
|
});
|
|
26
|
-
const OfferAnswerSchema = z.object({
|
|
27
|
-
ok: z.literal(true),
|
|
28
|
-
answer: z.object({
|
|
29
|
-
pairingId: z.string().min(1).max(128),
|
|
30
|
-
csrPem: z.string().min(1).max(16_384),
|
|
31
|
-
agentNonce: z.string().min(1).max(256),
|
|
32
|
-
expiresAt: z.number(),
|
|
30
|
+
const OfferAnswerSchema = zod_1.z.object({
|
|
31
|
+
ok: zod_1.z.literal(true),
|
|
32
|
+
answer: zod_1.z.object({
|
|
33
|
+
pairingId: zod_1.z.string().min(1).max(128),
|
|
34
|
+
csrPem: zod_1.z.string().min(1).max(16_384),
|
|
35
|
+
agentNonce: zod_1.z.string().min(1).max(256),
|
|
36
|
+
expiresAt: zod_1.z.number(),
|
|
33
37
|
}),
|
|
34
38
|
});
|
|
35
|
-
const PollSchema = z.object({
|
|
36
|
-
ok: z.literal(true),
|
|
37
|
-
poll: z.object({
|
|
38
|
-
state: z.enum(['pending', 'idle']),
|
|
39
|
-
localConfirmed: z.boolean(),
|
|
40
|
-
last: z
|
|
39
|
+
const PollSchema = zod_1.z.object({
|
|
40
|
+
ok: zod_1.z.literal(true),
|
|
41
|
+
poll: zod_1.z.object({
|
|
42
|
+
state: zod_1.z.enum(['pending', 'idle']),
|
|
43
|
+
localConfirmed: zod_1.z.boolean(),
|
|
44
|
+
last: zod_1.z
|
|
41
45
|
.object({
|
|
42
|
-
pairingId: z.string(),
|
|
43
|
-
outcome: z.enum(['completed', 'rejected', 'expired', 'code-mismatch', 'failed']),
|
|
46
|
+
pairingId: zod_1.z.string(),
|
|
47
|
+
outcome: zod_1.z.enum(['completed', 'rejected', 'expired', 'code-mismatch', 'failed']),
|
|
44
48
|
})
|
|
45
49
|
.nullable(),
|
|
46
50
|
}),
|
|
47
51
|
});
|
|
48
|
-
const FailureSchema = z.object({
|
|
49
|
-
error: z.string().optional(),
|
|
50
|
-
message: z.string().optional(),
|
|
52
|
+
const FailureSchema = zod_1.z.object({
|
|
53
|
+
error: zod_1.z.string().optional(),
|
|
54
|
+
message: zod_1.z.string().optional(),
|
|
51
55
|
});
|
|
52
56
|
/** A pairing target must be on the operator's own network. Throws with the reason. */
|
|
53
|
-
|
|
57
|
+
function assertPairableHost(host) {
|
|
54
58
|
const bare = host.replace(/^\[|\]$/g, '');
|
|
55
59
|
const isLoopback = bare === 'localhost' || bare === '::1' || bare.startsWith('127.');
|
|
56
60
|
if (isLoopback)
|
|
57
61
|
return;
|
|
58
|
-
if (isIP(bare) !== 0) {
|
|
59
|
-
if (isPrivateAddress(bare))
|
|
62
|
+
if ((0, node_net_1.isIP)(bare) !== 0) {
|
|
63
|
+
if ((0, system_1.isPrivateAddress)(bare))
|
|
60
64
|
return;
|
|
61
65
|
throw new Error(`"${host}" is not a private network address - an agent is paired from the LAN`);
|
|
62
66
|
}
|
|
63
|
-
if (isLocalOnlyHostname(bare.toLowerCase()))
|
|
67
|
+
if ((0, system_1.isLocalOnlyHostname)(bare.toLowerCase()))
|
|
64
68
|
return;
|
|
65
69
|
throw new Error(`"${host}" is not a local name - use the agent's LAN address or a .local / .lan host name`);
|
|
66
70
|
}
|
|
67
71
|
function baseUrl(endpoint) {
|
|
68
|
-
const host = isIP(endpoint.host) === 6 ? `[${endpoint.host}]` : endpoint.host;
|
|
72
|
+
const host = (0, node_net_1.isIP)(endpoint.host) === 6 ? `[${endpoint.host}]` : endpoint.host;
|
|
69
73
|
return `http://${host}:${endpoint.port}`;
|
|
70
74
|
}
|
|
71
75
|
async function readCapped(response) {
|
|
@@ -87,7 +91,7 @@ async function readCapped(response) {
|
|
|
87
91
|
}
|
|
88
92
|
return Buffer.concat(chunks).toString('utf8');
|
|
89
93
|
}
|
|
90
|
-
|
|
94
|
+
function createHttpAgentPairingTransport(options = {}) {
|
|
91
95
|
const fetchFn = options.fetchFn ?? fetch;
|
|
92
96
|
const timeoutMs = options.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
93
97
|
async function call(endpoint, method, path, schema, body) {
|
|
@@ -120,7 +124,7 @@ export function createHttpAgentPairingTransport(options = {}) {
|
|
|
120
124
|
const message = failure.success
|
|
121
125
|
? (failure.data.message ?? failure.data.error ?? `HTTP ${response.status}`)
|
|
122
126
|
: `HTTP ${response.status}`;
|
|
123
|
-
throw new PairingHttpError(response.status, code, message);
|
|
127
|
+
throw new system_1.PairingHttpError(response.status, code, message);
|
|
124
128
|
}
|
|
125
129
|
const parsed = schema.safeParse(json);
|
|
126
130
|
if (!parsed.success) {
|
|
@@ -128,19 +132,19 @@ export function createHttpAgentPairingTransport(options = {}) {
|
|
|
128
132
|
}
|
|
129
133
|
return parsed.data;
|
|
130
134
|
}
|
|
131
|
-
const Ok = z.object({ ok: z.literal(true) });
|
|
135
|
+
const Ok = zod_1.z.object({ ok: zod_1.z.literal(true) });
|
|
132
136
|
return {
|
|
133
|
-
hello: (endpoint) => call(endpoint, 'GET', PAIRING_PATHS.hello, HelloSchema),
|
|
134
|
-
offer: async (endpoint, body) => (await call(endpoint, 'POST', PAIRING_PATHS.offer, OfferAnswerSchema, body)).answer,
|
|
137
|
+
hello: (endpoint) => call(endpoint, 'GET', system_1.PAIRING_PATHS.hello, HelloSchema),
|
|
138
|
+
offer: async (endpoint, body) => (await call(endpoint, 'POST', system_1.PAIRING_PATHS.offer, OfferAnswerSchema, body)).answer,
|
|
135
139
|
reveal: async (endpoint, body) => {
|
|
136
|
-
await call(endpoint, 'POST', PAIRING_PATHS.reveal, Ok, body);
|
|
140
|
+
await call(endpoint, 'POST', system_1.PAIRING_PATHS.reveal, Ok, body);
|
|
137
141
|
},
|
|
138
|
-
poll: async (endpoint, pairingId) => (await call(endpoint, 'POST', PAIRING_PATHS.poll, PollSchema, { pairingId })).poll,
|
|
142
|
+
poll: async (endpoint, pairingId) => (await call(endpoint, 'POST', system_1.PAIRING_PATHS.poll, PollSchema, { pairingId })).poll,
|
|
139
143
|
complete: async (endpoint, body) => {
|
|
140
|
-
await call(endpoint, 'POST', PAIRING_PATHS.complete, Ok, body);
|
|
144
|
+
await call(endpoint, 'POST', system_1.PAIRING_PATHS.complete, Ok, body);
|
|
141
145
|
},
|
|
142
146
|
reject: async (endpoint, pairingId) => {
|
|
143
|
-
await call(endpoint, 'POST', PAIRING_PATHS.cancel, Ok, { pairingId });
|
|
147
|
+
await call(endpoint, 'POST', system_1.PAIRING_PATHS.cancel, Ok, { pairingId });
|
|
144
148
|
},
|
|
145
149
|
};
|
|
146
150
|
}
|