@camstack/server 1.2.592 → 1.2.594
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 +11 -50
- package/dist/agent/addon-scan.js +6 -44
- package/dist/agent/agent-addon-runtime.js +3 -8
- package/dist/agent/agent-addon-updates.js +12 -52
- package/dist/agent/agent-cap-dispatch-service.js +3 -5
- package/dist/agent/agent-config.js +7 -42
- package/dist/agent/agent-deploy-swap.js +5 -41
- package/dist/agent/agent-group-runner.js +8 -47
- package/dist/agent/agent-http-auth.js +10 -22
- package/dist/agent/agent-http.js +69 -115
- package/dist/agent/agent-hub-addon-update.js +10 -16
- package/dist/agent/agent-hub-registration.js +4 -7
- package/dist/agent/agent-infra-capabilities.js +5 -9
- package/dist/agent/agent-json-file.js +5 -42
- package/dist/agent/agent-mesh-gate.js +5 -8
- package/dist/agent/agent-node-certificates.js +25 -28
- package/dist/agent/agent-pairing-local.js +10 -47
- package/dist/agent/agent-pairing-routes.js +16 -20
- package/dist/agent/agent-pairing-store.js +18 -58
- package/dist/agent/agent-reconnect.js +1 -4
- package/dist/agent/agent-service.js +42 -78
- package/dist/agent/agent-sniffing-listener.js +11 -48
- package/dist/agent/agent-undeploy.js +5 -41
- package/dist/agent/agent-update-routes.js +14 -19
- package/dist/agent/agent-update-service.js +38 -80
- package/dist/agent/apply-model-distribution.js +1 -4
- package/dist/agent/apply-stage-dev-uploads.js +6 -9
- package/dist/agent/derive-hub-url.js +3 -8
- package/dist/agent/fetch-bundle-from-hub.js +6 -9
- package/dist/agent/hubs-found.js +6 -43
- package/dist/agent/infra-boot-guard.js +1 -4
- package/dist/agent/infra-boot-plan.js +2 -6
- package/dist/agent/main.js +158 -186
- package/dist/agent/register-agent-cap-dispatch.js +3 -6
- package/dist/agent/serial-queue.js +2 -7
- package/dist/agent-status-page.js +1 -4
- package/dist/api/addon-upload.js +22 -61
- package/dist/api/agent-addon-delivery.js +6 -11
- package/dist/api/auth-whoami.js +1 -4
- package/dist/api/backup-download-pump.js +5 -9
- package/dist/api/backup-download.js +7 -10
- package/dist/api/core/addon-settings.router.js +16 -19
- package/dist/api/core/agent-pairing.router.js +76 -79
- package/dist/api/core/agents.router.js +21 -24
- package/dist/api/core/auth-admin-tokens.procedures.js +48 -52
- package/dist/api/core/auth-device-cert.procedures.js +62 -67
- package/dist/api/core/auth-limits.js +16 -25
- package/dist/api/core/auth-reauth.procedures.js +32 -37
- package/dist/api/core/auth-revoke-credentials.procedures.js +22 -26
- package/dist/api/core/auth-sessions.procedures.js +52 -56
- package/dist/api/core/auth.router.js +300 -304
- package/dist/api/core/cap-providers.js +74 -121
- package/dist/api/core/capabilities.router.js +34 -37
- package/dist/api/core/capability-preference-writes.js +10 -17
- package/dist/api/core/certificates.router.js +106 -109
- package/dist/api/core/cluster-nodes.router.js +15 -18
- package/dist/api/core/collection-preference.js +2 -6
- package/dist/api/core/event-bus-proxy.router.js +34 -37
- package/dist/api/core/failure-contributions.js +4 -8
- package/dist/api/core/hwaccel.router.js +17 -20
- package/dist/api/core/integration-secrets.js +8 -12
- package/dist/api/core/lifecycle-job-runner.js +13 -49
- package/dist/api/core/live-events.router.js +29 -32
- package/dist/api/core/load-contributions.js +4 -8
- package/dist/api/core/logging-settings.js +30 -43
- package/dist/api/core/logs.router.js +40 -43
- package/dist/api/core/notifications.router.js +15 -18
- package/dist/api/core/public-event-filter.js +4 -8
- package/dist/api/core/repl.router.js +18 -21
- package/dist/api/core/request-census-settings.js +11 -16
- package/dist/api/core/server-management.provider.js +1 -4
- package/dist/api/core/server-name.js +9 -17
- package/dist/api/core/site-location.js +16 -24
- package/dist/api/core/stream-probe.router.js +21 -24
- package/dist/api/core/system-events.router.js +23 -26
- package/dist/api/cors/cors-policy.js +20 -29
- package/dist/api/cors/register-cors-policy.js +9 -14
- package/dist/api/deploy-stage-registry.js +6 -10
- package/dist/api/dev-uploads-bundle.js +12 -50
- package/dist/api/health/adaptive-probe.routes.js +9 -13
- package/dist/api/health/health.routes.js +8 -13
- package/dist/api/hub-cluster-url.js +3 -9
- package/dist/api/model-distributor.js +12 -50
- package/dist/api/oauth2/consent-page.js +10 -13
- package/dist/api/oauth2/oauth2-routes.js +17 -25
- package/dist/api/oauth2/private-host.js +1 -4
- package/dist/api/server-upload-propagate.js +15 -51
- package/dist/api/server-upload.js +13 -50
- package/dist/api/sse-no-compression.js +1 -4
- package/dist/api/static/frame-policy.js +4 -9
- package/dist/api/static/precompressed-asset.js +15 -57
- package/dist/api/static/spa-mount.js +8 -47
- package/dist/api/static/spa-static.js +5 -12
- package/dist/api/tarball-manifest.js +7 -44
- package/dist/api/trpc/cap-mount-helpers.js +7 -12
- package/dist/api/trpc/cap-route-error-formatter.js +10 -13
- package/dist/api/trpc/cap-router-runtime.js +40 -51
- package/dist/api/trpc/client-ip.js +9 -20
- package/dist/api/trpc/core-cap-bridge.js +32 -42
- package/dist/api/trpc/device-collection-dispatch.js +23 -27
- package/dist/api/trpc/device-config-secret-redaction.js +24 -40
- package/dist/api/trpc/generated-cap-mounts.js +219 -221
- package/dist/api/trpc/generated-cap-routers.js +4878 -4726
- package/dist/api/trpc/http-request-census-hook.js +8 -11
- package/dist/api/trpc/http-request-census.js +34 -41
- package/dist/api/trpc/http-request-census.singleton.js +4 -8
- package/dist/api/trpc/localized-schema-paths.js +1 -4
- package/dist/api/trpc/principal-visibility.js +14 -22
- package/dist/api/trpc/remote-addon-update-grant.js +1 -4
- package/dist/api/trpc/scope-access.js +10 -15
- package/dist/api/trpc/server-provided-caps.js +3 -7
- package/dist/api/trpc/share-view-access.js +6 -14
- package/dist/api/trpc/trpc-error-device-tags.js +3 -6
- package/dist/api/trpc/trpc-error-principal.js +2 -6
- package/dist/api/trpc/trpc.context.js +20 -25
- package/dist/api/trpc/trpc.middleware.js +38 -46
- package/dist/api/trpc/trpc.router.js +58 -99
- package/dist/api/trpc/user-error.js +5 -8
- package/dist/api/trpc/ws-request-census.js +17 -24
- package/dist/api/trpc/ws-slow-consumer-guard.js +11 -16
- package/dist/api/upload-auth.js +5 -9
- package/dist/auth/addon-route-jwt-gate.js +4 -7
- package/dist/auth/addon-route-share-gate.js +7 -12
- package/dist/auth/app-confirm-page.js +17 -22
- package/dist/auth/app-confirm-routes.js +26 -31
- package/dist/auth/app-confirmations.js +7 -44
- package/dist/auth/app-page-shell.js +17 -30
- package/dist/auth/app-page-strings.js +11 -17
- package/dist/auth/app-passkey-page.js +16 -21
- package/dist/auth/app-passkey-routes.js +37 -41
- package/dist/auth/app-refused-route.js +13 -18
- package/dist/auth/auth-network-policy.js +11 -15
- package/dist/auth/auth-provider-gate.js +4 -9
- package/dist/auth/auth-rate-limit.js +3 -7
- package/dist/auth/client-address.js +6 -9
- package/dist/auth/device-enroll-proofs.js +6 -43
- package/dist/auth/external-link-intents.js +3 -7
- package/dist/auth/hub-sessions.js +6 -12
- package/dist/auth/native-link-completions.js +7 -11
- package/dist/auth/native-return.js +9 -13
- package/dist/auth/passkey-provider.js +26 -32
- package/dist/auth/second-factors.js +6 -10
- package/dist/auth/session-connections.js +6 -12
- package/dist/auth/session-cookie.js +12 -23
- package/dist/auth/session-lifetimes.js +8 -12
- package/dist/auth/session-mint.js +4 -11
- package/dist/auth/sso-finish-app.js +13 -16
- package/dist/auth/sso-finish-deps.js +21 -27
- package/dist/auth/sso-finish.js +28 -38
- package/dist/auth/sso-routes.js +22 -25
- package/dist/auth/used-bridge-ids.js +1 -5
- package/dist/boot/boot-config.js +16 -55
- package/dist/boot/init-sequence.js +1 -4
- package/dist/boot/integration-id-backfill.js +3 -8
- package/dist/boot/platform-keychain-key.js +5 -42
- package/dist/boot/post-boot.service.js +14 -18
- package/dist/boot/reconcile-lifecycle-jobs.js +3 -6
- package/dist/boot/retired-public-url-env.js +4 -8
- package/dist/bootstrap-packages.js +1 -4
- package/dist/closure-node-modules.js +2 -38
- package/dist/closure-patches/patch-reach.json +6 -2
- package/dist/core/addon/addon-call-gateway.js +1 -5
- package/dist/core/addon/addon-package.service.js +83 -123
- package/dist/core/addon/addon-process-view.js +2 -6
- package/dist/core/addon/addon-realign-plan.js +1 -4
- package/dist/core/addon/addon-registry.service.js +254 -197
- package/dist/core/addon/addon-row-manifest.js +1 -4
- package/dist/core/addon/addon-search.service.js +3 -7
- package/dist/core/addon/addon-settings-provider.js +1 -3
- package/dist/core/addon/addon-uninstall.js +4 -11
- package/dist/core/addon/addon.tokens.js +2 -5
- package/dist/core/addon/device-meta-mirror.js +8 -13
- package/dist/core/addon/forked-custom-actions.js +6 -11
- package/dist/core/addon/integration-visibility.js +3 -6
- package/dist/core/addon/materialize-route-path.js +1 -4
- package/dist/core/addon/package-dir-utils.js +8 -45
- package/dist/core/addon/prune-misplaced-addons.js +5 -43
- package/dist/core/addon/runner-convergence.js +1 -4
- package/dist/core/addon/runner-serialization.js +1 -4
- package/dist/core/addon/runner-spawn-fanout.js +3 -8
- package/dist/core/addon/settings-door-wiring.js +5 -8
- package/dist/core/addon/single-flight-refresh.js +1 -4
- package/dist/core/addon-bridge/addon-bridge.service.js +7 -44
- package/dist/core/addon-pages/addon-pages.service.js +3 -40
- package/dist/core/addon-widgets/addon-widgets.service.js +4 -42
- package/dist/core/agent/agent-addon-backfill.js +9 -17
- package/dist/core/agent/agent-delivery-ledger.js +3 -7
- package/dist/core/agent/agent-liveness-event.js +2 -6
- package/dist/core/agent/agent-pairing-http.js +41 -45
- package/dist/core/agent/agent-registry.service.js +53 -92
- package/dist/core/agent/cluster-node-history-mirror.js +3 -7
- package/dist/core/agent/cluster-node-history-store.js +113 -58
- package/dist/core/agent/hub-agent-pairing.js +1 -5
- package/dist/core/agent/node-certificates-client.js +3 -6
- package/dist/core/agent/node-directory.js +1 -4
- package/dist/core/app-links/well-known-app-links.js +2 -6
- package/dist/core/auth/auth.service.js +3 -8
- package/dist/core/auth/handoff-code.service.js +11 -49
- package/dist/core/auth/record-kinds.js +35 -0
- package/dist/core/auth/share-token.service.js +174 -122
- package/dist/core/capability/capability.service.js +1 -5
- package/dist/core/config/config.schema.js +1 -6
- package/dist/core/config/config.service.js +2 -6
- package/dist/core/events/event-bus.service.js +3 -7
- package/dist/core/feature/feature.service.js +2 -6
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +5 -10
- package/dist/core/lifecycle/lifecycle-state-machine.js +1 -5
- package/dist/core/logging/log-ring-buffer.js +1 -5
- package/dist/core/logging/logging.service.js +5 -9
- package/dist/core/logging/scoped-logger.js +1 -5
- package/dist/core/moleculer/agent-readiness-pull.js +1 -4
- package/dist/core/moleculer/agent-registration-request.js +3 -7
- package/dist/core/moleculer/cap-call-fn.js +39 -5
- package/dist/core/moleculer/cap-route-authority.js +3 -8
- package/dist/core/moleculer/hub-mesh-guard.js +5 -9
- package/dist/core/moleculer/moleculer.service.js +108 -119
- package/dist/core/network/network-quality.service.js +2 -6
- package/dist/core/notification/notification-wrapper.service.js +3 -7
- package/dist/core/notification/toast-wrapper.service.js +3 -7
- package/dist/core/provider/provider.tokens.js +1 -4
- package/dist/core/repl/repl-engine.service.js +4 -8
- package/dist/core/runner-health/runner-boot-check.js +7 -15
- package/dist/core/runner-health/update-preflight.js +9 -14
- package/dist/core/server-update/server-update.service.js +12 -49
- package/dist/core/server-update/system-apply-closure-patches.js +6 -42
- package/dist/core/server-update/system-ensure-prebuilds.js +3 -6
- package/dist/core/server-update/system-exec-npm.js +2 -5
- package/dist/core/storage/fs-storage-backend.js +1 -5
- package/dist/core/storage/storage-location-manager.js +1 -5
- package/dist/core/storage/storage.service.js +2 -6
- package/dist/core/streaming/ffmpeg-stream-info.js +3 -8
- package/dist/core/streaming/stream-probe.service.js +12 -16
- package/dist/core/streaming/ttl-cache.js +1 -5
- package/dist/core/topology/topology-emitter.service.js +19 -23
- package/dist/core/update-availability-emitter.js +3 -7
- package/dist/core/update-availability-store.js +8 -45
- package/dist/core/updates/agent-installed-packages.js +5 -9
- package/dist/core/updates/restart-marker.js +3 -8
- package/dist/core/updates/update-check-scheduler.js +13 -18
- package/dist/core/updates/wrapper-update-checker.js +3 -7
- package/dist/first-boot-addon-plan.js +2 -6
- package/dist/framework-nodepath.js +2 -38
- package/dist/i18n/request-lang.js +7 -11
- package/dist/launcher.js +30 -65
- package/dist/lifecycle-journal-path.js +2 -38
- package/dist/main.js +287 -324
- package/dist/manual-boot.js +120 -157
- package/dist/node-role.js +1 -4
- package/dist/package-inventory.js +7 -48
- package/dist/pending-restore.js +7 -43
- package/dist/single-copy-cleanup-runner.js +9 -45
- package/dist/single-copy-cleanup.js +7 -15
- package/dist/sqlite-restore.js +9 -48
- package/dist/starter.js +4 -39
- package/dist/ui-serving/lazy-ui-serving.js +3 -39
- package/package.json +13 -13
|
@@ -1,41 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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"));
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
39
3
|
/**
|
|
40
4
|
* AddonPagesService — server-side helper that backs the static file
|
|
41
5
|
* route `/api/addon-pages/:addonId/*` (registered in `main.ts`).
|
|
@@ -53,7 +17,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
53
17
|
* addons can't be probed via path traversal tricks) and on
|
|
54
18
|
* `ConfigService` to locate the addons directory.
|
|
55
19
|
*/
|
|
56
|
-
class AddonPagesService {
|
|
20
|
+
export class AddonPagesService {
|
|
57
21
|
loggingService;
|
|
58
22
|
configService;
|
|
59
23
|
caps;
|
|
@@ -104,4 +68,3 @@ class AddonPagesService {
|
|
|
104
68
|
return path.resolve(dataPath, 'addons');
|
|
105
69
|
}
|
|
106
70
|
}
|
|
107
|
-
exports.AddonPagesService = AddonPagesService;
|
|
@@ -1,42 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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"));
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
40
3
|
/**
|
|
41
4
|
* Strip the `@<nodeId>` suffix the CapabilityBridge appends to
|
|
42
5
|
* collection-provider registry keys for cross-node addons. The widget
|
|
@@ -56,7 +19,7 @@ const VERSION_SEGMENT_RE = /^v[0-9a-f]{6,}$/;
|
|
|
56
19
|
* `{ filePath, versioned }` — `versioned` lets the route serve content-
|
|
57
20
|
* addressed files as `immutable`. Pure + exported for the spec.
|
|
58
21
|
*/
|
|
59
|
-
function stripBundleVersionSegment(rawPath) {
|
|
22
|
+
export function stripBundleVersionSegment(rawPath) {
|
|
60
23
|
const slash = rawPath.indexOf('/');
|
|
61
24
|
if (slash > 0 && VERSION_SEGMENT_RE.test(rawPath.slice(0, slash))) {
|
|
62
25
|
return { filePath: rawPath.slice(slash + 1), versioned: true };
|
|
@@ -82,7 +45,7 @@ function stripBundleVersionSegment(rawPath) {
|
|
|
82
45
|
* `dist/<entryId>/`) resolve to the right sub-folder instead of the
|
|
83
46
|
* pre-bundle `addons/@camstack/addon-<id>/dist/` layout.
|
|
84
47
|
*/
|
|
85
|
-
class AddonWidgetsService {
|
|
48
|
+
export class AddonWidgetsService {
|
|
86
49
|
loggingService;
|
|
87
50
|
caps;
|
|
88
51
|
registry;
|
|
@@ -138,4 +101,3 @@ class AddonWidgetsService {
|
|
|
138
101
|
return resolvedFile;
|
|
139
102
|
}
|
|
140
103
|
}
|
|
141
|
-
exports.AddonWidgetsService = AddonWidgetsService;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Node addon back-fill — converge a node to the addon roster THAT NODE last
|
|
4
3
|
* declared.
|
|
@@ -49,12 +48,6 @@
|
|
|
49
48
|
* This module is pure/seam-driven on purpose: the decision of what a node should
|
|
50
49
|
* have is asserted in unit tests with no Moleculer, filesystem or npm registry.
|
|
51
50
|
*/
|
|
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;
|
|
58
51
|
/** Triggers permitted to install packages onto a node. */
|
|
59
52
|
const DELIVERING_TRIGGERS = new Set([
|
|
60
53
|
'node-registration',
|
|
@@ -62,14 +55,14 @@ const DELIVERING_TRIGGERS = new Set([
|
|
|
62
55
|
'operator-repair',
|
|
63
56
|
]);
|
|
64
57
|
/** Is this trigger allowed to put bytes on a node? */
|
|
65
|
-
function triggerMayDeliver(trigger) {
|
|
58
|
+
export function triggerMayDeliver(trigger) {
|
|
66
59
|
return DELIVERING_TRIGGERS.has(trigger);
|
|
67
60
|
}
|
|
68
61
|
/**
|
|
69
62
|
* Decide what a node is missing relative to its own last-declared roster.
|
|
70
63
|
* Pure — no I/O, no clock, no randomness.
|
|
71
64
|
*/
|
|
72
|
-
function computeBackfillPlan(input) {
|
|
65
|
+
export function computeBackfillPlan(input) {
|
|
73
66
|
const liveNames = new Set(input.live.map((p) => p.name));
|
|
74
67
|
const targets = [];
|
|
75
68
|
const retired = [];
|
|
@@ -94,7 +87,7 @@ function computeBackfillPlan(input) {
|
|
|
94
87
|
}
|
|
95
88
|
return { targets, retired, notOnHub, liveCount: liveNames.size };
|
|
96
89
|
}
|
|
97
|
-
function confirmBackfillPlan(plan, secondRead) {
|
|
90
|
+
export function confirmBackfillPlan(plan, secondRead) {
|
|
98
91
|
const present = new Set(secondRead.map((p) => p.name));
|
|
99
92
|
const targets = plan.targets.filter((t) => !present.has(t.name));
|
|
100
93
|
const contradicted = plan.targets.filter((t) => present.has(t.name));
|
|
@@ -105,7 +98,7 @@ function confirmBackfillPlan(plan, secondRead) {
|
|
|
105
98
|
* Mirrors `CrashSupervisor.MAX_CRASHES_IN_WINDOW` in intent: bounded, terminal,
|
|
106
99
|
* loud — never an infinite retry loop.
|
|
107
100
|
*/
|
|
108
|
-
|
|
101
|
+
export const MAX_BACKFILL_ATTEMPTS = 3;
|
|
109
102
|
/**
|
|
110
103
|
* Per-`(node, package)` delivery circuit breaker. In-memory and process-scoped
|
|
111
104
|
* on purpose: it bounds retries within one hub lifetime, and a hub restart is an
|
|
@@ -113,7 +106,7 @@ exports.MAX_BACKFILL_ATTEMPTS = 3;
|
|
|
113
106
|
* `CrashSupervisor`). It stores no intent — the durable record of what a node
|
|
114
107
|
* should have lives in `ClusterNodeHistoryStore`, not here.
|
|
115
108
|
*/
|
|
116
|
-
class BackfillAttemptTracker {
|
|
109
|
+
export class BackfillAttemptTracker {
|
|
117
110
|
failures = new Map();
|
|
118
111
|
forNode(nodeId) {
|
|
119
112
|
const existing = this.failures.get(nodeId);
|
|
@@ -130,7 +123,7 @@ class BackfillAttemptTracker {
|
|
|
130
123
|
return new Set();
|
|
131
124
|
const retired = new Set();
|
|
132
125
|
for (const [name, state] of node) {
|
|
133
|
-
if (state.attempts >=
|
|
126
|
+
if (state.attempts >= MAX_BACKFILL_ATTEMPTS)
|
|
134
127
|
retired.add(name);
|
|
135
128
|
}
|
|
136
129
|
return retired;
|
|
@@ -144,7 +137,7 @@ class BackfillAttemptTracker {
|
|
|
144
137
|
name,
|
|
145
138
|
version: state.version,
|
|
146
139
|
attempts: state.attempts,
|
|
147
|
-
retired: state.attempts >=
|
|
140
|
+
retired: state.attempts >= MAX_BACKFILL_ATTEMPTS,
|
|
148
141
|
lastError: state.lastError,
|
|
149
142
|
}));
|
|
150
143
|
}
|
|
@@ -154,7 +147,7 @@ class BackfillAttemptTracker {
|
|
|
154
147
|
// A different hub version is a new fact — it earns a fresh set of attempts.
|
|
155
148
|
const attempts = prior && prior.version === version ? prior.attempts + 1 : 1;
|
|
156
149
|
node.set(name, { version, attempts, lastError: error });
|
|
157
|
-
return { attempts, retired: attempts >=
|
|
150
|
+
return { attempts, retired: attempts >= MAX_BACKFILL_ATTEMPTS };
|
|
158
151
|
}
|
|
159
152
|
recordSuccess(nodeId, name) {
|
|
160
153
|
this.failures.get(nodeId)?.delete(name);
|
|
@@ -164,13 +157,12 @@ class BackfillAttemptTracker {
|
|
|
164
157
|
this.failures.delete(nodeId);
|
|
165
158
|
}
|
|
166
159
|
}
|
|
167
|
-
exports.BackfillAttemptTracker = BackfillAttemptTracker;
|
|
168
160
|
/**
|
|
169
161
|
* Deliver every planned package, then reload the node ONCE. Per-package failures
|
|
170
162
|
* are isolated and counted — one broken package must not stop the others, and
|
|
171
163
|
* must not retry forever.
|
|
172
164
|
*/
|
|
173
|
-
async function executeBackfill(seam, nodeId, plan, tracker) {
|
|
165
|
+
export async function executeBackfill(seam, nodeId, plan, tracker) {
|
|
174
166
|
const delivered = [];
|
|
175
167
|
const failed = [];
|
|
176
168
|
for (const target of plan.targets) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* "Is the hub currently writing addons to this node?"
|
|
4
3
|
*
|
|
@@ -34,8 +33,6 @@
|
|
|
34
33
|
* carrying nothing durable. Losing it on a restart is correct — a hub that just
|
|
35
34
|
* restarted has no delivery in flight.
|
|
36
35
|
*/
|
|
37
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.AgentDeliveryLedger = exports.DELIVERY_GRACE_MS = void 0;
|
|
39
36
|
/**
|
|
40
37
|
* How long after a delivery finishes the node stays protected from a back-fill.
|
|
41
38
|
*
|
|
@@ -44,8 +41,8 @@ exports.AgentDeliveryLedger = exports.DELIVERY_GRACE_MS = void 0;
|
|
|
44
41
|
* group runner — 12 on `little-unraid`) land over the following seconds. Each
|
|
45
42
|
* one fires a reconcile.
|
|
46
43
|
*/
|
|
47
|
-
|
|
48
|
-
class AgentDeliveryLedger {
|
|
44
|
+
export const DELIVERY_GRACE_MS = 60_000;
|
|
45
|
+
export class AgentDeliveryLedger {
|
|
49
46
|
byNode = new Map();
|
|
50
47
|
forNode(nodeId) {
|
|
51
48
|
const existing = this.byNode.get(nodeId);
|
|
@@ -91,7 +88,7 @@ class AgentDeliveryLedger {
|
|
|
91
88
|
if (!state)
|
|
92
89
|
return null;
|
|
93
90
|
const since = state.lastFinishedAt === 0 ? null : now - state.lastFinishedAt;
|
|
94
|
-
if (state.inFlight === 0 && (since === null || since >=
|
|
91
|
+
if (state.inFlight === 0 && (since === null || since >= DELIVERY_GRACE_MS)) {
|
|
95
92
|
// Window closed — drop the package memory so a later suppression names
|
|
96
93
|
// only the packages of the delivery that caused it.
|
|
97
94
|
state.packages.clear();
|
|
@@ -109,4 +106,3 @@ class AgentDeliveryLedger {
|
|
|
109
106
|
this.byNode.delete(nodeId);
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
|
-
exports.AgentDeliveryLedger = AgentDeliveryLedger;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.agentOfflineData = agentOfflineData;
|
|
4
|
-
exports.nodeDisplayName = nodeDisplayName;
|
|
5
1
|
/**
|
|
6
2
|
* The payload of `agent.offline`, built from what Moleculer told us.
|
|
7
3
|
*
|
|
@@ -10,7 +6,7 @@ exports.nodeDisplayName = nodeDisplayName;
|
|
|
10
6
|
* DISCONNECT on a clean stop. The notification centre turns it into the body
|
|
11
7
|
* of the "node offline" notification (D820).
|
|
12
8
|
*/
|
|
13
|
-
function agentOfflineData(agentId, unexpected, nodeName) {
|
|
9
|
+
export function agentOfflineData(agentId, unexpected, nodeName) {
|
|
14
10
|
return {
|
|
15
11
|
agentId,
|
|
16
12
|
...(nodeName !== undefined ? { nodeName } : {}),
|
|
@@ -20,7 +16,7 @@ function agentOfflineData(agentId, unexpected, nodeName) {
|
|
|
20
16
|
};
|
|
21
17
|
}
|
|
22
18
|
/** The history's display name for a node — only a real one, never the id echoed back. */
|
|
23
|
-
function nodeDisplayName(nodeId, history) {
|
|
19
|
+
export function nodeDisplayName(nodeId, history) {
|
|
24
20
|
const name = history?.find((row) => row.id === nodeId)?.name;
|
|
25
21
|
return name !== undefined && name.length > 0 && name !== nodeId ? name : undefined;
|
|
26
22
|
}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertPairableHost = assertPairableHost;
|
|
4
|
-
exports.createHttpAgentPairingTransport = createHttpAgentPairingTransport;
|
|
5
1
|
/**
|
|
6
2
|
* The hub's HTTP client for an agent's pairing endpoints (D857).
|
|
7
3
|
*
|
|
@@ -15,61 +11,61 @@ exports.createHttpAgentPairingTransport = createHttpAgentPairingTransport;
|
|
|
15
11
|
* the operator's own network, never to a public address (the hub must not be a
|
|
16
12
|
* way to make requests to arbitrary hosts).
|
|
17
13
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
import { isIP } from 'node:net';
|
|
15
|
+
import { isLocalOnlyHostname, isPrivateAddress, PAIRING_PATHS, PairingHttpError, } from '@camstack/system';
|
|
16
|
+
import { z } from 'zod';
|
|
21
17
|
const REQUEST_TIMEOUT_MS = 8_000;
|
|
22
18
|
const MAX_RESPONSE_BYTES = 128 * 1024;
|
|
23
|
-
const HelloSchema =
|
|
24
|
-
protocol:
|
|
25
|
-
nodeId:
|
|
26
|
-
version:
|
|
27
|
-
state:
|
|
28
|
-
pendingExpiresAt:
|
|
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(),
|
|
29
25
|
});
|
|
30
|
-
const OfferAnswerSchema =
|
|
31
|
-
ok:
|
|
32
|
-
answer:
|
|
33
|
-
pairingId:
|
|
34
|
-
csrPem:
|
|
35
|
-
agentNonce:
|
|
36
|
-
expiresAt:
|
|
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(),
|
|
37
33
|
}),
|
|
38
34
|
});
|
|
39
|
-
const PollSchema =
|
|
40
|
-
ok:
|
|
41
|
-
poll:
|
|
42
|
-
state:
|
|
43
|
-
localConfirmed:
|
|
44
|
-
last:
|
|
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
|
|
45
41
|
.object({
|
|
46
|
-
pairingId:
|
|
47
|
-
outcome:
|
|
42
|
+
pairingId: z.string(),
|
|
43
|
+
outcome: z.enum(['completed', 'rejected', 'expired', 'code-mismatch', 'failed']),
|
|
48
44
|
})
|
|
49
45
|
.nullable(),
|
|
50
46
|
}),
|
|
51
47
|
});
|
|
52
|
-
const FailureSchema =
|
|
53
|
-
error:
|
|
54
|
-
message:
|
|
48
|
+
const FailureSchema = z.object({
|
|
49
|
+
error: z.string().optional(),
|
|
50
|
+
message: z.string().optional(),
|
|
55
51
|
});
|
|
56
52
|
/** A pairing target must be on the operator's own network. Throws with the reason. */
|
|
57
|
-
function assertPairableHost(host) {
|
|
53
|
+
export function assertPairableHost(host) {
|
|
58
54
|
const bare = host.replace(/^\[|\]$/g, '');
|
|
59
55
|
const isLoopback = bare === 'localhost' || bare === '::1' || bare.startsWith('127.');
|
|
60
56
|
if (isLoopback)
|
|
61
57
|
return;
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
58
|
+
if (isIP(bare) !== 0) {
|
|
59
|
+
if (isPrivateAddress(bare))
|
|
64
60
|
return;
|
|
65
61
|
throw new Error(`"${host}" is not a private network address - an agent is paired from the LAN`);
|
|
66
62
|
}
|
|
67
|
-
if (
|
|
63
|
+
if (isLocalOnlyHostname(bare.toLowerCase()))
|
|
68
64
|
return;
|
|
69
65
|
throw new Error(`"${host}" is not a local name - use the agent's LAN address or a .local / .lan host name`);
|
|
70
66
|
}
|
|
71
67
|
function baseUrl(endpoint) {
|
|
72
|
-
const host =
|
|
68
|
+
const host = isIP(endpoint.host) === 6 ? `[${endpoint.host}]` : endpoint.host;
|
|
73
69
|
return `http://${host}:${endpoint.port}`;
|
|
74
70
|
}
|
|
75
71
|
async function readCapped(response) {
|
|
@@ -91,7 +87,7 @@ async function readCapped(response) {
|
|
|
91
87
|
}
|
|
92
88
|
return Buffer.concat(chunks).toString('utf8');
|
|
93
89
|
}
|
|
94
|
-
function createHttpAgentPairingTransport(options = {}) {
|
|
90
|
+
export function createHttpAgentPairingTransport(options = {}) {
|
|
95
91
|
const fetchFn = options.fetchFn ?? fetch;
|
|
96
92
|
const timeoutMs = options.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
97
93
|
async function call(endpoint, method, path, schema, body) {
|
|
@@ -124,7 +120,7 @@ function createHttpAgentPairingTransport(options = {}) {
|
|
|
124
120
|
const message = failure.success
|
|
125
121
|
? (failure.data.message ?? failure.data.error ?? `HTTP ${response.status}`)
|
|
126
122
|
: `HTTP ${response.status}`;
|
|
127
|
-
throw new
|
|
123
|
+
throw new PairingHttpError(response.status, code, message);
|
|
128
124
|
}
|
|
129
125
|
const parsed = schema.safeParse(json);
|
|
130
126
|
if (!parsed.success) {
|
|
@@ -132,19 +128,19 @@ function createHttpAgentPairingTransport(options = {}) {
|
|
|
132
128
|
}
|
|
133
129
|
return parsed.data;
|
|
134
130
|
}
|
|
135
|
-
const Ok =
|
|
131
|
+
const Ok = z.object({ ok: z.literal(true) });
|
|
136
132
|
return {
|
|
137
|
-
hello: (endpoint) => call(endpoint, 'GET',
|
|
138
|
-
offer: async (endpoint, body) => (await call(endpoint, 'POST',
|
|
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,
|
|
139
135
|
reveal: async (endpoint, body) => {
|
|
140
|
-
await call(endpoint, 'POST',
|
|
136
|
+
await call(endpoint, 'POST', PAIRING_PATHS.reveal, Ok, body);
|
|
141
137
|
},
|
|
142
|
-
poll: async (endpoint, pairingId) => (await call(endpoint, 'POST',
|
|
138
|
+
poll: async (endpoint, pairingId) => (await call(endpoint, 'POST', PAIRING_PATHS.poll, PollSchema, { pairingId })).poll,
|
|
143
139
|
complete: async (endpoint, body) => {
|
|
144
|
-
await call(endpoint, 'POST',
|
|
140
|
+
await call(endpoint, 'POST', PAIRING_PATHS.complete, Ok, body);
|
|
145
141
|
},
|
|
146
142
|
reject: async (endpoint, pairingId) => {
|
|
147
|
-
await call(endpoint, 'POST',
|
|
143
|
+
await call(endpoint, 'POST', PAIRING_PATHS.cancel, Ok, { pairingId });
|
|
148
144
|
},
|
|
149
145
|
};
|
|
150
146
|
}
|