camstack 1.2.36 → 1.2.38
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.
|
@@ -14522,7 +14522,7 @@ function date4(params) {
|
|
|
14522
14522
|
// ../../node_modules/zod/v4/classic/external.js
|
|
14523
14523
|
config(en_default());
|
|
14524
14524
|
|
|
14525
|
-
// ../types/dist/sleep-
|
|
14525
|
+
// ../types/dist/sleep-B8EIZt4h.mjs
|
|
14526
14526
|
var WELL_KNOWN_TABS = [
|
|
14527
14527
|
{
|
|
14528
14528
|
id: "overview",
|
|
@@ -27017,6 +27017,13 @@ var CameraStatusSchema = external_exports.object({
|
|
|
27017
27017
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
27018
27018
|
fetchedAt: external_exports.number()
|
|
27019
27019
|
});
|
|
27020
|
+
var INFERENCE_DEVICE_EXCLUSION_REASONS = [
|
|
27021
|
+
"disabled",
|
|
27022
|
+
"unavailable",
|
|
27023
|
+
"cannot-host-camera-root",
|
|
27024
|
+
"accelerator-preferred"
|
|
27025
|
+
];
|
|
27026
|
+
var InferenceDeviceExclusionReasonSchema = external_exports.enum(INFERENCE_DEVICE_EXCLUSION_REASONS);
|
|
27020
27027
|
var NodeInferenceDeviceSchema = external_exports.object({
|
|
27021
27028
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
27022
27029
|
key: external_exports.string(),
|
|
@@ -27047,7 +27054,17 @@ var NodeInferenceDeviceSchema = external_exports.object({
|
|
|
27047
27054
|
* available per format; this is the stored selection that becomes the
|
|
27048
27055
|
* default for EVERY camera landing on this accelerator.
|
|
27049
27056
|
*/
|
|
27050
|
-
steps: external_exports.record(external_exports.string(), DeviceStepConfigSchema).optional()
|
|
27057
|
+
steps: external_exports.record(external_exports.string(), DeviceStepConfigSchema).optional(),
|
|
27058
|
+
/**
|
|
27059
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
27060
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
27061
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
27062
|
+
* never disagree with the election — deriving it in the UI from
|
|
27063
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
27064
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
27065
|
+
* "an accelerator is serving" predicate).
|
|
27066
|
+
*/
|
|
27067
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
27051
27068
|
});
|
|
27052
27069
|
var NodeInferenceDevicesSchema = external_exports.object({
|
|
27053
27070
|
nodeId: external_exports.string(),
|
|
@@ -32057,7 +32074,35 @@ var ConnectionEndpointSchema = external_exports.object({
|
|
|
32057
32074
|
*/
|
|
32058
32075
|
priority: external_exports.number()
|
|
32059
32076
|
});
|
|
32060
|
-
var
|
|
32077
|
+
var LocalPortSourceEnum = external_exports.enum([
|
|
32078
|
+
"server-config",
|
|
32079
|
+
"server-env",
|
|
32080
|
+
"caller-hint",
|
|
32081
|
+
"default"
|
|
32082
|
+
]);
|
|
32083
|
+
var AdvertisedLocalPortSchema = external_exports.object({
|
|
32084
|
+
port: external_exports.number().int().min(1).max(65535),
|
|
32085
|
+
source: LocalPortSourceEnum
|
|
32086
|
+
});
|
|
32087
|
+
var GetConnectionEndpointsResultSchema = external_exports.object({
|
|
32088
|
+
endpoints: external_exports.array(ConnectionEndpointSchema).readonly(),
|
|
32089
|
+
/**
|
|
32090
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
32091
|
+
* came from.
|
|
32092
|
+
*
|
|
32093
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
32094
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
32095
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
32096
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
32097
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
32098
|
+
* `caller-hint` is the hub's own socket.
|
|
32099
|
+
*
|
|
32100
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
32101
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
32102
|
+
* `caller-hint`.
|
|
32103
|
+
*/
|
|
32104
|
+
localPort: AdvertisedLocalPortSchema
|
|
32105
|
+
});
|
|
32061
32106
|
var NotificationEndpointSchema = external_exports.object({
|
|
32062
32107
|
/** The operator's explicit choice, or null for AUTO. */
|
|
32063
32108
|
baseUrl: external_exports.string().nullable(),
|
|
@@ -32099,10 +32144,35 @@ var localNetworkCapability = {
|
|
|
32099
32144
|
* Honours `getAllowedAddresses()` when set — addresses outside
|
|
32100
32145
|
* the allowlist are dropped (the public tunnel + loopback are
|
|
32101
32146
|
* always included as escape hatches).
|
|
32147
|
+
*
|
|
32148
|
+
* **The port is the hub's, not the caller's** (D62 — a function's fact
|
|
32149
|
+
* belongs to whoever already owns it). This method used to take a `port`
|
|
32150
|
+
* and echo it onto every LAN and loopback URL it advertised, which made
|
|
32151
|
+
* every client a second authority on a socket only the hub binds. A viewer
|
|
32152
|
+
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
32153
|
+
* infers 443 from the scheme, asks with 443, and was handed
|
|
32154
|
+
* `https://192.168.1.9:443` for a hub listening on 4443. That candidate
|
|
32155
|
+
* cannot ever answer, and losing its race reads in the log exactly like
|
|
32156
|
+
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
32157
|
+
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
32158
|
+
* dead on every single connect.
|
|
32159
|
+
*
|
|
32160
|
+
* The hub now resolves its own listen port and reports it as `localPort`,
|
|
32161
|
+
* with the SOURCE of the number, so a client can tell a fact from an echo.
|
|
32162
|
+
*
|
|
32163
|
+
* Out of scope on purpose: a LAN URL that is not the hub's own socket (a
|
|
32164
|
+
* reverse proxy in front of it on another port) is not this method's to
|
|
32165
|
+
* invent either — pin it with `setNotificationEndpoint` / a configured
|
|
32166
|
+
* origin, which is an operator statement rather than a guess.
|
|
32102
32167
|
*/
|
|
32103
32168
|
getConnectionEndpoints: method(external_exports.object({
|
|
32104
|
-
/**
|
|
32105
|
-
|
|
32169
|
+
/**
|
|
32170
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
32171
|
+
* written against the echoing contract keep working; the hub uses it
|
|
32172
|
+
* only when it cannot read its own port, and says so via
|
|
32173
|
+
* `localPort.source === 'caller-hint'`.
|
|
32174
|
+
*/
|
|
32175
|
+
port: external_exports.number().int().min(1).max(65535).optional(),
|
|
32106
32176
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
32107
32177
|
* candidate. Default `true`. */
|
|
32108
32178
|
includeLoopback: external_exports.boolean().optional(),
|
|
@@ -36593,6 +36663,7 @@ var BATTERY_DEVICE_PROFILE = {
|
|
|
36593
36663
|
settings: {}
|
|
36594
36664
|
};
|
|
36595
36665
|
var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
|
|
36666
|
+
var OPERATOR_WRITTEN_STALE_MS = 10 * 6e4;
|
|
36596
36667
|
var METHOD_ACCESS_MAP = Object.freeze({
|
|
36597
36668
|
"accessories.setChildHidden": {
|
|
36598
36669
|
capName: "accessories",
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDiscover
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UYHYTS5M.js";
|
|
5
5
|
import "./chunk-LMMQX4CK.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
@@ -38,7 +38,7 @@ async function runServe(args) {
|
|
|
38
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
39
39
|
};
|
|
40
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
41
|
-
await import("./launcher-
|
|
41
|
+
await import("./launcher-SCKDFMNR.js");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/commands/agent.ts
|
|
@@ -83,7 +83,7 @@ async function runAgent(args) {
|
|
|
83
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
84
84
|
};
|
|
85
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
86
|
-
await import("./launcher-
|
|
86
|
+
await import("./launcher-SCKDFMNR.js");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/commands/setup.ts
|
|
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
|
|
|
1130
1130
|
return true;
|
|
1131
1131
|
}
|
|
1132
1132
|
async function resolveServerInteractive(presetNamespace) {
|
|
1133
|
-
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-
|
|
1133
|
+
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-5NNX7OG3.js");
|
|
1134
1134
|
if (presetNamespace) {
|
|
1135
1135
|
const spinner4 = clack.spinner();
|
|
1136
1136
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|
|
@@ -23631,9 +23631,9 @@ var require_zod = __commonJS({
|
|
|
23631
23631
|
}
|
|
23632
23632
|
});
|
|
23633
23633
|
|
|
23634
|
-
// ../system/dist/dist-
|
|
23635
|
-
var
|
|
23636
|
-
"../system/dist/dist-
|
|
23634
|
+
// ../system/dist/dist-iAwSA2_f.js
|
|
23635
|
+
var require_dist_iAwSA2_f = __commonJS({
|
|
23636
|
+
"../system/dist/dist-iAwSA2_f.js"(exports) {
|
|
23637
23637
|
"use strict";
|
|
23638
23638
|
var zod = require_zod();
|
|
23639
23639
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -23641,6 +23641,7 @@ var require_dist_B2CtwVW2 = __commonJS({
|
|
|
23641
23641
|
EventCategory2["SystemAddonsReady"] = "system.addons-ready";
|
|
23642
23642
|
EventCategory2["SystemRestarting"] = "system.restarting";
|
|
23643
23643
|
EventCategory2["SystemRestartCompleted"] = "system.restart-completed";
|
|
23644
|
+
EventCategory2["SystemTlsCertChanged"] = "system.tls-cert-changed";
|
|
23644
23645
|
EventCategory2["UpdateAvailable"] = "update.available";
|
|
23645
23646
|
EventCategory2["SystemReadyState"] = "system.ready-state";
|
|
23646
23647
|
EventCategory2["AddonStarted"] = "addon.started";
|
|
@@ -37300,6 +37301,12 @@ var require_dist_B2CtwVW2 = __commonJS({
|
|
|
37300
37301
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
37301
37302
|
fetchedAt: zod.z.number()
|
|
37302
37303
|
});
|
|
37304
|
+
var InferenceDeviceExclusionReasonSchema = zod.z.enum([
|
|
37305
|
+
"disabled",
|
|
37306
|
+
"unavailable",
|
|
37307
|
+
"cannot-host-camera-root",
|
|
37308
|
+
"accelerator-preferred"
|
|
37309
|
+
]);
|
|
37303
37310
|
var NodeInferenceDeviceSchema = zod.z.object({
|
|
37304
37311
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
37305
37312
|
key: zod.z.string(),
|
|
@@ -37330,7 +37337,17 @@ var require_dist_B2CtwVW2 = __commonJS({
|
|
|
37330
37337
|
* available per format; this is the stored selection that becomes the
|
|
37331
37338
|
* default for EVERY camera landing on this accelerator.
|
|
37332
37339
|
*/
|
|
37333
|
-
steps: zod.z.record(zod.z.string(), DeviceStepConfigSchema).optional()
|
|
37340
|
+
steps: zod.z.record(zod.z.string(), DeviceStepConfigSchema).optional(),
|
|
37341
|
+
/**
|
|
37342
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
37343
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
37344
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
37345
|
+
* never disagree with the election — deriving it in the UI from
|
|
37346
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
37347
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
37348
|
+
* "an accelerator is serving" predicate).
|
|
37349
|
+
*/
|
|
37350
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
37334
37351
|
});
|
|
37335
37352
|
var NodeInferenceDevicesSchema = zod.z.object({
|
|
37336
37353
|
nodeId: zod.z.string(),
|
|
@@ -42339,7 +42356,35 @@ var require_dist_B2CtwVW2 = __commonJS({
|
|
|
42339
42356
|
*/
|
|
42340
42357
|
priority: zod.z.number()
|
|
42341
42358
|
});
|
|
42342
|
-
var
|
|
42359
|
+
var LocalPortSourceEnum = zod.z.enum([
|
|
42360
|
+
"server-config",
|
|
42361
|
+
"server-env",
|
|
42362
|
+
"caller-hint",
|
|
42363
|
+
"default"
|
|
42364
|
+
]);
|
|
42365
|
+
var AdvertisedLocalPortSchema = zod.z.object({
|
|
42366
|
+
port: zod.z.number().int().min(1).max(65535),
|
|
42367
|
+
source: LocalPortSourceEnum
|
|
42368
|
+
});
|
|
42369
|
+
var GetConnectionEndpointsResultSchema = zod.z.object({
|
|
42370
|
+
endpoints: zod.z.array(ConnectionEndpointSchema).readonly(),
|
|
42371
|
+
/**
|
|
42372
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
42373
|
+
* came from.
|
|
42374
|
+
*
|
|
42375
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
42376
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
42377
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
42378
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
42379
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
42380
|
+
* `caller-hint` is the hub's own socket.
|
|
42381
|
+
*
|
|
42382
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
42383
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
42384
|
+
* `caller-hint`.
|
|
42385
|
+
*/
|
|
42386
|
+
localPort: AdvertisedLocalPortSchema
|
|
42387
|
+
});
|
|
42343
42388
|
var NotificationEndpointSchema = zod.z.object({
|
|
42344
42389
|
/** The operator's explicit choice, or null for AUTO. */
|
|
42345
42390
|
baseUrl: zod.z.string().nullable(),
|
|
@@ -42381,10 +42426,35 @@ var require_dist_B2CtwVW2 = __commonJS({
|
|
|
42381
42426
|
* Honours `getAllowedAddresses()` when set — addresses outside
|
|
42382
42427
|
* the allowlist are dropped (the public tunnel + loopback are
|
|
42383
42428
|
* always included as escape hatches).
|
|
42429
|
+
*
|
|
42430
|
+
* **The port is the hub's, not the caller's** (D62 — a function's fact
|
|
42431
|
+
* belongs to whoever already owns it). This method used to take a `port`
|
|
42432
|
+
* and echo it onto every LAN and loopback URL it advertised, which made
|
|
42433
|
+
* every client a second authority on a socket only the hub binds. A viewer
|
|
42434
|
+
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
42435
|
+
* infers 443 from the scheme, asks with 443, and was handed
|
|
42436
|
+
* `https://192.168.1.9:443` for a hub listening on 4443. That candidate
|
|
42437
|
+
* cannot ever answer, and losing its race reads in the log exactly like
|
|
42438
|
+
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
42439
|
+
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
42440
|
+
* dead on every single connect.
|
|
42441
|
+
*
|
|
42442
|
+
* The hub now resolves its own listen port and reports it as `localPort`,
|
|
42443
|
+
* with the SOURCE of the number, so a client can tell a fact from an echo.
|
|
42444
|
+
*
|
|
42445
|
+
* Out of scope on purpose: a LAN URL that is not the hub's own socket (a
|
|
42446
|
+
* reverse proxy in front of it on another port) is not this method's to
|
|
42447
|
+
* invent either — pin it with `setNotificationEndpoint` / a configured
|
|
42448
|
+
* origin, which is an operator statement rather than a guess.
|
|
42384
42449
|
*/
|
|
42385
42450
|
getConnectionEndpoints: method(zod.z.object({
|
|
42386
|
-
/**
|
|
42387
|
-
|
|
42451
|
+
/**
|
|
42452
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
42453
|
+
* written against the echoing contract keep working; the hub uses it
|
|
42454
|
+
* only when it cannot read its own port, and says so via
|
|
42455
|
+
* `localPort.source === 'caller-hint'`.
|
|
42456
|
+
*/
|
|
42457
|
+
port: zod.z.number().int().min(1).max(65535).optional(),
|
|
42388
42458
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
42389
42459
|
* candidate. Default `true`. */
|
|
42390
42460
|
includeLoopback: zod.z.boolean().optional(),
|
|
@@ -56186,7 +56256,7 @@ var require_alerts_addon = __commonJS({
|
|
|
56186
56256
|
[Symbol.toStringTag]: { value: "Module" }
|
|
56187
56257
|
});
|
|
56188
56258
|
require_chunk_Cek0wNdY();
|
|
56189
|
-
var require_dist10 =
|
|
56259
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
56190
56260
|
function selectExpired(alerts, cutoffMs) {
|
|
56191
56261
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
56192
56262
|
}
|
|
@@ -56238,6 +56308,10 @@ var require_alerts_addon = __commonJS({
|
|
|
56238
56308
|
severity: "warning",
|
|
56239
56309
|
titleTemplate: "System restarting"
|
|
56240
56310
|
},
|
|
56311
|
+
"system.tls-cert-changed": {
|
|
56312
|
+
severity: "warning",
|
|
56313
|
+
titleTemplate: "TLS certificate changed"
|
|
56314
|
+
},
|
|
56241
56315
|
"device.registered": {
|
|
56242
56316
|
severity: "info",
|
|
56243
56317
|
titleTemplate: "Device registered"
|
|
@@ -56726,6 +56800,8 @@ var require_alerts_addon = __commonJS({
|
|
|
56726
56800
|
return `Storage critical for device "${deviceId ?? "unknown"}"`;
|
|
56727
56801
|
case "system.boot":
|
|
56728
56802
|
return `System booted in "${data.mode ?? "unknown"}" mode`;
|
|
56803
|
+
case "system.tls-cert-changed":
|
|
56804
|
+
return data.caRotated === true ? `TLS certificate reissued (${String(data.reason)}) \u2014 the local CA also changed. Re-install ${String(data.caCertPath)} on any device that trusted the old one.` : `TLS certificate reissued (${String(data.reason)}) \u2014 the local CA is unchanged, previously trusted devices keep working.`;
|
|
56729
56805
|
case "process.crashed":
|
|
56730
56806
|
return `Process "${processId ?? "unknown"}" crashed`;
|
|
56731
56807
|
default:
|
|
@@ -56999,7 +57075,7 @@ var require_console_logging = __commonJS({
|
|
|
56999
57075
|
[Symbol.toStringTag]: { value: "Module" }
|
|
57000
57076
|
});
|
|
57001
57077
|
require_chunk_Cek0wNdY();
|
|
57002
|
-
var require_dist10 =
|
|
57078
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
57003
57079
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
57004
57080
|
var LEVEL_RANK = {
|
|
57005
57081
|
debug: 0,
|
|
@@ -57093,7 +57169,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
57093
57169
|
"use strict";
|
|
57094
57170
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
57095
57171
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
57096
|
-
var require_dist10 =
|
|
57172
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
57097
57173
|
var node_crypto = __require("crypto");
|
|
57098
57174
|
var node_fs_promises = __require("fs/promises");
|
|
57099
57175
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -57990,11 +58066,11 @@ var require_core_blocks = __commonJS({
|
|
|
57990
58066
|
}
|
|
57991
58067
|
});
|
|
57992
58068
|
|
|
57993
|
-
// ../system/dist/retired-settings-keys-
|
|
57994
|
-
var
|
|
57995
|
-
"../system/dist/retired-settings-keys-
|
|
58069
|
+
// ../system/dist/retired-settings-keys-OfhqQio4.js
|
|
58070
|
+
var require_retired_settings_keys_OfhqQio4 = __commonJS({
|
|
58071
|
+
"../system/dist/retired-settings-keys-OfhqQio4.js"(exports) {
|
|
57996
58072
|
"use strict";
|
|
57997
|
-
var require_dist10 =
|
|
58073
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
57998
58074
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
57999
58075
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
58000
58076
|
return raw === "" || raw === "hub";
|
|
@@ -60037,8 +60113,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
60037
60113
|
[Symbol.toStringTag]: { value: "Module" }
|
|
60038
60114
|
});
|
|
60039
60115
|
require_chunk_Cek0wNdY();
|
|
60040
|
-
var require_dist10 =
|
|
60041
|
-
var require_retired_settings_keys =
|
|
60116
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
60117
|
+
var require_retired_settings_keys = require_retired_settings_keys_OfhqQio4();
|
|
60042
60118
|
var node_crypto = __require("crypto");
|
|
60043
60119
|
var _camstack_types_node = require_node();
|
|
60044
60120
|
var JOB_HISTORY = 20;
|
|
@@ -64365,7 +64441,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
64365
64441
|
[Symbol.toStringTag]: { value: "Module" }
|
|
64366
64442
|
});
|
|
64367
64443
|
require_chunk_Cek0wNdY();
|
|
64368
|
-
var require_dist10 =
|
|
64444
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
64369
64445
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
64370
64446
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
64371
64447
|
var HubForwarderDestination = class {
|
|
@@ -64502,7 +64578,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
64502
64578
|
"use strict";
|
|
64503
64579
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
64504
64580
|
require_chunk_Cek0wNdY();
|
|
64505
|
-
var require_dist10 =
|
|
64581
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
64506
64582
|
var NO_DEVICES = "liveness:no-devices";
|
|
64507
64583
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
64508
64584
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -64692,7 +64768,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
64692
64768
|
[Symbol.toStringTag]: { value: "Module" }
|
|
64693
64769
|
});
|
|
64694
64770
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
64695
|
-
var require_dist10 =
|
|
64771
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
64696
64772
|
var node_crypto = __require("crypto");
|
|
64697
64773
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
64698
64774
|
var crypto$1 = __require("crypto");
|
|
@@ -72376,7 +72452,7 @@ var require_loki_logging = __commonJS({
|
|
|
72376
72452
|
[Symbol.toStringTag]: { value: "Module" }
|
|
72377
72453
|
});
|
|
72378
72454
|
require_chunk_Cek0wNdY();
|
|
72379
|
-
var require_dist10 =
|
|
72455
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
72380
72456
|
function sanitizeLabelName(raw) {
|
|
72381
72457
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
72382
72458
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -72941,7 +73017,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
72941
73017
|
[Symbol.toStringTag]: { value: "Module" }
|
|
72942
73018
|
});
|
|
72943
73019
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
72944
|
-
var require_dist10 =
|
|
73020
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
72945
73021
|
var node_child_process = __require("child_process");
|
|
72946
73022
|
var node_util = __require("util");
|
|
72947
73023
|
var node_os = __require("os");
|
|
@@ -73883,7 +73959,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
73883
73959
|
[Symbol.toStringTag]: { value: "Module" }
|
|
73884
73960
|
});
|
|
73885
73961
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
73886
|
-
var require_dist10 =
|
|
73962
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
73887
73963
|
var node_crypto = __require("crypto");
|
|
73888
73964
|
var node_fs_promises = __require("fs/promises");
|
|
73889
73965
|
var node_path = __require("path");
|
|
@@ -74999,8 +75075,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
74999
75075
|
[Symbol.toStringTag]: { value: "Module" }
|
|
75000
75076
|
});
|
|
75001
75077
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
75002
|
-
var require_dist10 =
|
|
75003
|
-
var require_retired_settings_keys =
|
|
75078
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
75079
|
+
var require_retired_settings_keys = require_retired_settings_keys_OfhqQio4();
|
|
75004
75080
|
var node_crypto = __require("crypto");
|
|
75005
75081
|
var node_fs = __require("fs");
|
|
75006
75082
|
var node_module = __require("module");
|
|
@@ -76544,7 +76620,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
76544
76620
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76545
76621
|
});
|
|
76546
76622
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
76547
|
-
var require_dist10 =
|
|
76623
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
76548
76624
|
var node_crypto = __require("crypto");
|
|
76549
76625
|
var node_fs_promises = __require("fs/promises");
|
|
76550
76626
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -78423,7 +78499,7 @@ var require_system_config_addon = __commonJS({
|
|
|
78423
78499
|
[Symbol.toStringTag]: { value: "Module" }
|
|
78424
78500
|
});
|
|
78425
78501
|
require_chunk_Cek0wNdY();
|
|
78426
|
-
var require_dist10 =
|
|
78502
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
78427
78503
|
var SECTION_TITLES = {
|
|
78428
78504
|
server: "Server",
|
|
78429
78505
|
auth: "Authentication"
|
|
@@ -96484,7 +96560,7 @@ var require_winston_logging = __commonJS({
|
|
|
96484
96560
|
[Symbol.toStringTag]: { value: "Module" }
|
|
96485
96561
|
});
|
|
96486
96562
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
96487
|
-
var require_dist10 =
|
|
96563
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
96488
96564
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
96489
96565
|
var node_path = __require("path");
|
|
96490
96566
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -97472,15 +97548,16 @@ var require_file_data_plane_DUHPHa_Y = __commonJS({
|
|
|
97472
97548
|
}
|
|
97473
97549
|
});
|
|
97474
97550
|
|
|
97475
|
-
// ../types/dist/event-category-
|
|
97476
|
-
var
|
|
97477
|
-
"../types/dist/event-category-
|
|
97551
|
+
// ../types/dist/event-category-EY0GNjV9.js
|
|
97552
|
+
var require_event_category_EY0GNjV9 = __commonJS({
|
|
97553
|
+
"../types/dist/event-category-EY0GNjV9.js"(exports) {
|
|
97478
97554
|
"use strict";
|
|
97479
97555
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
97480
97556
|
EventCategory2["SystemBoot"] = "system.boot";
|
|
97481
97557
|
EventCategory2["SystemAddonsReady"] = "system.addons-ready";
|
|
97482
97558
|
EventCategory2["SystemRestarting"] = "system.restarting";
|
|
97483
97559
|
EventCategory2["SystemRestartCompleted"] = "system.restart-completed";
|
|
97560
|
+
EventCategory2["SystemTlsCertChanged"] = "system.tls-cert-changed";
|
|
97484
97561
|
EventCategory2["UpdateAvailable"] = "update.available";
|
|
97485
97562
|
EventCategory2["SystemReadyState"] = "system.ready-state";
|
|
97486
97563
|
EventCategory2["AddonStarted"] = "addon.started";
|
|
@@ -97638,11 +97715,11 @@ var require_event_category_CRPORAAz = __commonJS({
|
|
|
97638
97715
|
}
|
|
97639
97716
|
});
|
|
97640
97717
|
|
|
97641
|
-
// ../types/dist/sleep-
|
|
97642
|
-
var
|
|
97643
|
-
"../types/dist/sleep-
|
|
97718
|
+
// ../types/dist/sleep-C2XhJhkd.js
|
|
97719
|
+
var require_sleep_C2XhJhkd = __commonJS({
|
|
97720
|
+
"../types/dist/sleep-C2XhJhkd.js"(exports) {
|
|
97644
97721
|
"use strict";
|
|
97645
|
-
var require_event_category =
|
|
97722
|
+
var require_event_category = require_event_category_EY0GNjV9();
|
|
97646
97723
|
var zod = require_zod();
|
|
97647
97724
|
var WELL_KNOWN_TABS = [
|
|
97648
97725
|
{
|
|
@@ -101079,8 +101156,8 @@ var require_addon = __commonJS({
|
|
|
101079
101156
|
"../types/dist/addon.js"(exports) {
|
|
101080
101157
|
"use strict";
|
|
101081
101158
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
101082
|
-
var require_event_category =
|
|
101083
|
-
var require_sleep =
|
|
101159
|
+
var require_event_category = require_event_category_EY0GNjV9();
|
|
101160
|
+
var require_sleep = require_sleep_C2XhJhkd();
|
|
101084
101161
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
101085
101162
|
var CAP_INPUT_DEFAULTS = Object.freeze({
|
|
101086
101163
|
"addons": { "getLogs": { "limit": 100 } },
|
|
@@ -107954,9 +108031,9 @@ var require_dist2 = __commonJS({
|
|
|
107954
108031
|
}
|
|
107955
108032
|
});
|
|
107956
108033
|
|
|
107957
|
-
// ../system/dist/manifest-python-deps-
|
|
107958
|
-
var
|
|
107959
|
-
"../system/dist/manifest-python-deps-
|
|
108034
|
+
// ../system/dist/manifest-python-deps-CwBbX4Ut.js
|
|
108035
|
+
var require_manifest_python_deps_CwBbX4Ut = __commonJS({
|
|
108036
|
+
"../system/dist/manifest-python-deps-CwBbX4Ut.js"(exports) {
|
|
107960
108037
|
"use strict";
|
|
107961
108038
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
107962
108039
|
var node_crypto = __require("crypto");
|
|
@@ -107977,8 +108054,8 @@ var require_manifest_python_deps_MA_BZGBz = __commonJS({
|
|
|
107977
108054
|
var node_vm = __require("vm");
|
|
107978
108055
|
node_vm = require_chunk.__toESM(node_vm);
|
|
107979
108056
|
var _camstack_types_addon = require_addon();
|
|
107980
|
-
var _trpc_client = require_dist2();
|
|
107981
108057
|
var node_net = __require("net");
|
|
108058
|
+
var _trpc_client = require_dist2();
|
|
107982
108059
|
var HEAP_WATCH_INTERVAL_MS = 6e4;
|
|
107983
108060
|
var HEAP_WATCH_WARN_RATIO = 0.8;
|
|
107984
108061
|
var HEAP_WATCH_ESCALATE_RATIO = 0.7;
|
|
@@ -118760,7 +118837,7 @@ var require_dist3 = __commonJS({
|
|
|
118760
118837
|
"use strict";
|
|
118761
118838
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
118762
118839
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
118763
|
-
var require_dist10 =
|
|
118840
|
+
var require_dist10 = require_dist_iAwSA2_f();
|
|
118764
118841
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
118765
118842
|
require_alerts();
|
|
118766
118843
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -118785,7 +118862,7 @@ var require_dist3 = __commonJS({
|
|
|
118785
118862
|
require_system_config();
|
|
118786
118863
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
118787
118864
|
var require_file_data_plane = require_file_data_plane_DUHPHa_Y();
|
|
118788
|
-
var require_manifest_python_deps =
|
|
118865
|
+
var require_manifest_python_deps = require_manifest_python_deps_CwBbX4Ut();
|
|
118789
118866
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
118790
118867
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
118791
118868
|
var zod = require_zod();
|
|
@@ -118806,6 +118883,7 @@ var require_dist3 = __commonJS({
|
|
|
118806
118883
|
var node_vm = __require("vm");
|
|
118807
118884
|
node_vm = require_chunk.__toESM(node_vm);
|
|
118808
118885
|
var _camstack_types_addon = require_addon();
|
|
118886
|
+
var node_net = __require("net");
|
|
118809
118887
|
var node_url = __require("url");
|
|
118810
118888
|
var node_events = __require("events");
|
|
118811
118889
|
var node_stream = __require("stream");
|
|
@@ -120570,63 +120648,330 @@ var require_dist3 = __commonJS({
|
|
|
120570
120648
|
};
|
|
120571
120649
|
}
|
|
120572
120650
|
};
|
|
120573
|
-
var
|
|
120574
|
-
|
|
120575
|
-
|
|
120576
|
-
|
|
120577
|
-
|
|
120578
|
-
|
|
120579
|
-
|
|
120580
|
-
|
|
120581
|
-
|
|
120582
|
-
|
|
120583
|
-
|
|
120584
|
-
|
|
120651
|
+
var SERVER_AUTH_OID = "1.3.6.1.5.5.7.3.1";
|
|
120652
|
+
var MAX_LEAF_VALIDITY_DAYS = 397;
|
|
120653
|
+
var LEAF_RENEWAL_WINDOW_DAYS = 30;
|
|
120654
|
+
var CA_VALIDITY_DAYS = 3650;
|
|
120655
|
+
var MS_PER_DAY = 864e5;
|
|
120656
|
+
var REASONS_REQUIRING_NEW_CA = [
|
|
120657
|
+
"missing",
|
|
120658
|
+
"unreadable",
|
|
120659
|
+
"no-local-ca",
|
|
120660
|
+
"ca-expiring"
|
|
120661
|
+
];
|
|
120662
|
+
function reasonRequiresNewCa(reason) {
|
|
120663
|
+
return REASONS_REQUIRING_NEW_CA.includes(reason);
|
|
120664
|
+
}
|
|
120665
|
+
function parse$1(pem) {
|
|
120666
|
+
try {
|
|
120667
|
+
return new node_crypto.X509Certificate(pem);
|
|
120585
120668
|
} catch {
|
|
120669
|
+
return null;
|
|
120586
120670
|
}
|
|
120587
|
-
|
|
120588
|
-
|
|
120589
|
-
|
|
120590
|
-
|
|
120671
|
+
}
|
|
120672
|
+
function daysBetween(from, to) {
|
|
120673
|
+
return (to.getTime() - from.getTime()) / MS_PER_DAY;
|
|
120674
|
+
}
|
|
120675
|
+
function hasServerAuthEku(leaf) {
|
|
120676
|
+
const eku = leaf.keyUsage;
|
|
120677
|
+
return eku !== void 0 && eku.length === 1 && eku[0] === "1.3.6.1.5.5.7.3.1";
|
|
120678
|
+
}
|
|
120679
|
+
function keyMatches(leaf, keyPem) {
|
|
120680
|
+
try {
|
|
120681
|
+
return leaf.checkPrivateKey((0, node_crypto.createPrivateKey)(keyPem));
|
|
120682
|
+
} catch {
|
|
120683
|
+
return false;
|
|
120684
|
+
}
|
|
120685
|
+
}
|
|
120686
|
+
function coversIdentity(leaf, identity) {
|
|
120687
|
+
for (const name2 of identity.requiredDnsNames) if (leaf.checkHost(name2) === void 0) return false;
|
|
120688
|
+
for (const ip of identity.requiredIpAddresses) if (leaf.checkIP(ip) === void 0) return false;
|
|
120689
|
+
return true;
|
|
120690
|
+
}
|
|
120691
|
+
function evaluateExistingCert(input) {
|
|
120692
|
+
const leaf = parse$1(input.chainPem);
|
|
120693
|
+
const ca = parse$1(input.caPem);
|
|
120694
|
+
if (leaf === null || ca === null) return "unreadable";
|
|
120695
|
+
if (daysBetween(input.now, new Date(ca.validTo)) < 427) return "ca-expiring";
|
|
120696
|
+
if (!keyMatches(leaf, input.keyPem)) return "key-mismatch";
|
|
120697
|
+
if (daysBetween(input.now, new Date(leaf.validTo)) < 30) return "expiring";
|
|
120698
|
+
if (!hasServerAuthEku(leaf)) return "missing-server-auth-eku";
|
|
120699
|
+
if (leaf.ca || !leaf.checkIssued(ca) || !leaf.verify(ca.publicKey)) return "not-issued-by-local-ca";
|
|
120700
|
+
if (daysBetween(new Date(leaf.validFrom), new Date(leaf.validTo)) > 398) return "validity-too-long";
|
|
120701
|
+
if (!coversIdentity(leaf, input.identity)) return "san-coverage-gap";
|
|
120702
|
+
return null;
|
|
120703
|
+
}
|
|
120704
|
+
var VOLATILE_INTERFACE_PREFIXES = [
|
|
120705
|
+
"docker",
|
|
120706
|
+
"br-",
|
|
120707
|
+
"veth",
|
|
120708
|
+
"virbr",
|
|
120709
|
+
"cni",
|
|
120710
|
+
"flannel",
|
|
120711
|
+
"tun",
|
|
120712
|
+
"utun",
|
|
120713
|
+
"tap",
|
|
120714
|
+
"wg",
|
|
120715
|
+
"zt",
|
|
120716
|
+
"tailscale",
|
|
120717
|
+
"ppp",
|
|
120718
|
+
"awdl",
|
|
120719
|
+
"llw"
|
|
120720
|
+
];
|
|
120721
|
+
var DNS_NAME_PATTERN = /^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
120722
|
+
function isIpv4(value) {
|
|
120723
|
+
return (0, node_net.isIP)(value) === 4;
|
|
120724
|
+
}
|
|
120725
|
+
function isIpv6(value) {
|
|
120726
|
+
return (0, node_net.isIP)(value) === 6;
|
|
120727
|
+
}
|
|
120728
|
+
function isLinkLocal(value) {
|
|
120729
|
+
if (isIpv4(value)) return value.startsWith("169.254.");
|
|
120730
|
+
if (!isIpv6(value)) return false;
|
|
120731
|
+
const firstGroup = value.split(":")[0] ?? "";
|
|
120732
|
+
if (firstGroup === "") return false;
|
|
120733
|
+
const parsed = Number.parseInt(firstGroup, 16);
|
|
120734
|
+
return Number.isFinite(parsed) && (parsed & 65472) === 65152;
|
|
120735
|
+
}
|
|
120736
|
+
function isUniqueLocalIpv6(value) {
|
|
120737
|
+
if (!isIpv6(value)) return false;
|
|
120738
|
+
const firstGroup = value.split(":")[0] ?? "";
|
|
120739
|
+
const parsed = Number.parseInt(firstGroup, 16);
|
|
120740
|
+
return Number.isFinite(parsed) && (parsed & 65024) === 64512;
|
|
120741
|
+
}
|
|
120742
|
+
function isVolatileInterface(name2) {
|
|
120743
|
+
const lower = name2.toLowerCase();
|
|
120744
|
+
return VOLATILE_INTERFACE_PREFIXES.some((prefix) => lower.startsWith(prefix));
|
|
120745
|
+
}
|
|
120746
|
+
function isStableGateAddress(address) {
|
|
120747
|
+
if (isLinkLocal(address)) return false;
|
|
120748
|
+
if (isIpv4(address)) return true;
|
|
120749
|
+
return isUniqueLocalIpv6(address);
|
|
120750
|
+
}
|
|
120751
|
+
function addSan(dns, ips, value) {
|
|
120752
|
+
const trimmed = value.trim();
|
|
120753
|
+
if (trimmed === "") return;
|
|
120754
|
+
if ((0, node_net.isIP)(trimmed) !== 0) {
|
|
120755
|
+
if (!isLinkLocal(trimmed)) ips.add(trimmed);
|
|
120756
|
+
return;
|
|
120757
|
+
}
|
|
120758
|
+
if (DNS_NAME_PATTERN.test(trimmed)) dns.add(trimmed);
|
|
120759
|
+
}
|
|
120760
|
+
function collectCertIdentity(options) {
|
|
120761
|
+
const dnsNames = /* @__PURE__ */ new Set();
|
|
120762
|
+
const ipAddresses = /* @__PURE__ */ new Set(["127.0.0.1", "::1"]);
|
|
120763
|
+
const requiredDnsNames = /* @__PURE__ */ new Set();
|
|
120764
|
+
const requiredIpAddresses = /* @__PURE__ */ new Set(["127.0.0.1"]);
|
|
120765
|
+
for (const name2 of [
|
|
120591
120766
|
"localhost",
|
|
120592
|
-
|
|
120767
|
+
options.commonName,
|
|
120593
120768
|
node_os.hostname()
|
|
120594
|
-
])
|
|
120595
|
-
|
|
120596
|
-
|
|
120597
|
-
|
|
120598
|
-
|
|
120599
|
-
|
|
120600
|
-
|
|
120601
|
-
|
|
120602
|
-
|
|
120603
|
-
|
|
120604
|
-
|
|
120605
|
-
for (const
|
|
120606
|
-
|
|
120769
|
+
]) {
|
|
120770
|
+
addSan(dnsNames, ipAddresses, name2);
|
|
120771
|
+
addSan(requiredDnsNames, requiredIpAddresses, name2);
|
|
120772
|
+
}
|
|
120773
|
+
for (const [ifaceName, addrs] of Object.entries(node_os.networkInterfaces())) for (const addr of addrs ?? []) {
|
|
120774
|
+
if (addr.internal) continue;
|
|
120775
|
+
if (isLinkLocal(addr.address)) continue;
|
|
120776
|
+
ipAddresses.add(addr.address);
|
|
120777
|
+
if (isVolatileInterface(ifaceName)) continue;
|
|
120778
|
+
if (isStableGateAddress(addr.address)) requiredIpAddresses.add(addr.address);
|
|
120779
|
+
}
|
|
120780
|
+
for (const san of options.extraSans) {
|
|
120781
|
+
addSan(dnsNames, ipAddresses, san);
|
|
120782
|
+
addSan(requiredDnsNames, requiredIpAddresses, san);
|
|
120783
|
+
}
|
|
120784
|
+
return {
|
|
120785
|
+
dnsNames: [...dnsNames],
|
|
120786
|
+
ipAddresses: [...ipAddresses],
|
|
120787
|
+
requiredDnsNames: [...requiredDnsNames],
|
|
120788
|
+
requiredIpAddresses: [...requiredIpAddresses]
|
|
120789
|
+
};
|
|
120790
|
+
}
|
|
120791
|
+
var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
|
|
120792
|
+
var CA_COMMON_NAME = "CamStack Local CA";
|
|
120793
|
+
function sanValue(identity) {
|
|
120794
|
+
const parts = [];
|
|
120795
|
+
for (const dns of identity.dnsNames) parts.push(`DNS:${dns}`);
|
|
120796
|
+
for (const ip of identity.ipAddresses) if ((0, node_net.isIP)(ip) !== 0) parts.push(`IP:${ip}`);
|
|
120797
|
+
return parts.join(",");
|
|
120798
|
+
}
|
|
120799
|
+
async function generateCa(tmpDir) {
|
|
120800
|
+
const caCertPath = (0, node_path.join)(tmpDir, "ca.crt");
|
|
120801
|
+
const caKeyPath = (0, node_path.join)(tmpDir, "ca.key");
|
|
120607
120802
|
await execFileAsync$3("openssl", [
|
|
120608
120803
|
"req",
|
|
120609
120804
|
"-x509",
|
|
120610
120805
|
"-newkey",
|
|
120611
120806
|
"rsa:2048",
|
|
120807
|
+
"-nodes",
|
|
120808
|
+
"-sha256",
|
|
120809
|
+
"-days",
|
|
120810
|
+
String(CA_VALIDITY_DAYS),
|
|
120811
|
+
"-keyout",
|
|
120812
|
+
caKeyPath,
|
|
120813
|
+
"-out",
|
|
120814
|
+
caCertPath,
|
|
120815
|
+
"-subj",
|
|
120816
|
+
`/CN=${CA_COMMON_NAME}`,
|
|
120817
|
+
"-addext",
|
|
120818
|
+
"basicConstraints=critical,CA:TRUE,pathlen:0",
|
|
120819
|
+
"-addext",
|
|
120820
|
+
"keyUsage=critical,keyCertSign,cRLSign",
|
|
120821
|
+
"-addext",
|
|
120822
|
+
"subjectKeyIdentifier=hash"
|
|
120823
|
+
]);
|
|
120824
|
+
await (0, node_fs_promises.chmod)(caKeyPath, 384);
|
|
120825
|
+
return {
|
|
120826
|
+
caCertPath,
|
|
120827
|
+
caKeyPath
|
|
120828
|
+
};
|
|
120829
|
+
}
|
|
120830
|
+
async function issueLeaf(tmpDir, ca, identity, commonName, validDays) {
|
|
120831
|
+
const keyPath = (0, node_path.join)(tmpDir, "leaf.key");
|
|
120832
|
+
const csrPath = (0, node_path.join)(tmpDir, "leaf.csr");
|
|
120833
|
+
const certPath = (0, node_path.join)(tmpDir, "leaf.crt");
|
|
120834
|
+
const extPath = (0, node_path.join)(tmpDir, "leaf.ext");
|
|
120835
|
+
await (0, node_fs_promises.writeFile)(extPath, [
|
|
120836
|
+
"basicConstraints=critical,CA:FALSE",
|
|
120837
|
+
"keyUsage=critical,digitalSignature,keyEncipherment",
|
|
120838
|
+
"extendedKeyUsage=serverAuth",
|
|
120839
|
+
"subjectKeyIdentifier=hash",
|
|
120840
|
+
"authorityKeyIdentifier=keyid,issuer",
|
|
120841
|
+
`subjectAltName=${sanValue(identity)}`,
|
|
120842
|
+
""
|
|
120843
|
+
].join("\n"), "utf-8");
|
|
120844
|
+
await execFileAsync$3("openssl", [
|
|
120845
|
+
"req",
|
|
120846
|
+
"-new",
|
|
120847
|
+
"-newkey",
|
|
120848
|
+
"rsa:2048",
|
|
120849
|
+
"-nodes",
|
|
120850
|
+
"-sha256",
|
|
120612
120851
|
"-keyout",
|
|
120613
120852
|
keyPath,
|
|
120614
120853
|
"-out",
|
|
120615
|
-
|
|
120854
|
+
csrPath,
|
|
120855
|
+
"-subj",
|
|
120856
|
+
`/CN=${commonName}`
|
|
120857
|
+
]);
|
|
120858
|
+
await execFileAsync$3("openssl", [
|
|
120859
|
+
"x509",
|
|
120860
|
+
"-req",
|
|
120861
|
+
"-in",
|
|
120862
|
+
csrPath,
|
|
120863
|
+
"-CA",
|
|
120864
|
+
ca.caCertPath,
|
|
120865
|
+
"-CAkey",
|
|
120866
|
+
ca.caKeyPath,
|
|
120867
|
+
"-set_serial",
|
|
120868
|
+
`0x00${(0, node_crypto.randomBytes)(16).toString("hex")}`,
|
|
120616
120869
|
"-days",
|
|
120617
120870
|
String(validDays),
|
|
120618
|
-
"-
|
|
120619
|
-
"-
|
|
120620
|
-
|
|
120621
|
-
"-
|
|
120622
|
-
|
|
120871
|
+
"-sha256",
|
|
120872
|
+
"-extfile",
|
|
120873
|
+
extPath,
|
|
120874
|
+
"-out",
|
|
120875
|
+
certPath
|
|
120623
120876
|
]);
|
|
120624
|
-
|
|
120625
|
-
await
|
|
120877
|
+
await (0, node_fs_promises.chmod)(keyPath, 384);
|
|
120878
|
+
await (0, node_fs_promises.rm)(csrPath, { force: true });
|
|
120879
|
+
await (0, node_fs_promises.rm)(extPath, { force: true });
|
|
120626
120880
|
return {
|
|
120627
120881
|
certPath,
|
|
120628
|
-
keyPath
|
|
120629
|
-
|
|
120882
|
+
keyPath
|
|
120883
|
+
};
|
|
120884
|
+
}
|
|
120885
|
+
var DEFAULT_COMMON_NAME = "camstack.local";
|
|
120886
|
+
async function ensureTlsCert(dataDir, options) {
|
|
120887
|
+
const tlsDir = (0, node_path.join)(dataDir, "tls");
|
|
120888
|
+
const paths = {
|
|
120889
|
+
certPath: (0, node_path.join)(tlsDir, "camstack.crt"),
|
|
120890
|
+
keyPath: (0, node_path.join)(tlsDir, "camstack.key"),
|
|
120891
|
+
caCertPath: (0, node_path.join)(tlsDir, "camstack-ca.crt"),
|
|
120892
|
+
caKeyPath: (0, node_path.join)(tlsDir, "camstack-ca.key")
|
|
120893
|
+
};
|
|
120894
|
+
const commonName = options?.commonName ?? DEFAULT_COMMON_NAME;
|
|
120895
|
+
const validDays = Math.min(options?.validDays ?? 397, 397);
|
|
120896
|
+
const identity = collectCertIdentity({
|
|
120897
|
+
commonName,
|
|
120898
|
+
extraSans: options?.extraSans ?? []
|
|
120899
|
+
});
|
|
120900
|
+
const reason = decideRegeneration(paths, identity);
|
|
120901
|
+
if (reason === null) return describe(paths, false, null, false, null);
|
|
120902
|
+
const previousFingerprint = readFingerprint(paths.certPath);
|
|
120903
|
+
const caRotated = reasonRequiresNewCa(reason);
|
|
120904
|
+
(0, node_fs.mkdirSync)(tlsDir, { recursive: true });
|
|
120905
|
+
await regenerate(paths, identity, commonName, validDays, caRotated);
|
|
120906
|
+
return describe(paths, true, reason, caRotated, previousFingerprint);
|
|
120907
|
+
}
|
|
120908
|
+
function readFingerprint(certPath) {
|
|
120909
|
+
try {
|
|
120910
|
+
return new node_crypto.X509Certificate((0, node_fs.readFileSync)(certPath)).fingerprint256;
|
|
120911
|
+
} catch {
|
|
120912
|
+
return null;
|
|
120913
|
+
}
|
|
120914
|
+
}
|
|
120915
|
+
function decideRegeneration(paths, identity) {
|
|
120916
|
+
if (!(0, node_fs.existsSync)(paths.certPath) || !(0, node_fs.existsSync)(paths.keyPath)) return "missing";
|
|
120917
|
+
if (!(0, node_fs.existsSync)(paths.caCertPath) || !(0, node_fs.existsSync)(paths.caKeyPath)) return "no-local-ca";
|
|
120918
|
+
try {
|
|
120919
|
+
return evaluateExistingCert({
|
|
120920
|
+
chainPem: (0, node_fs.readFileSync)(paths.certPath, "utf-8"),
|
|
120921
|
+
keyPem: (0, node_fs.readFileSync)(paths.keyPath, "utf-8"),
|
|
120922
|
+
caPem: (0, node_fs.readFileSync)(paths.caCertPath, "utf-8"),
|
|
120923
|
+
identity,
|
|
120924
|
+
now: /* @__PURE__ */ new Date()
|
|
120925
|
+
});
|
|
120926
|
+
} catch {
|
|
120927
|
+
return "unreadable";
|
|
120928
|
+
}
|
|
120929
|
+
}
|
|
120930
|
+
async function regenerate(paths, identity, commonName, validDays, newCa) {
|
|
120931
|
+
const scratch = await (0, node_fs_promises.mkdtemp)((0, node_path.join)((0, node_os.tmpdir)(), "camstack-tls-"));
|
|
120932
|
+
try {
|
|
120933
|
+
const ca = newCa ? await generateCa(scratch) : {
|
|
120934
|
+
caCertPath: paths.caCertPath,
|
|
120935
|
+
caKeyPath: paths.caKeyPath
|
|
120936
|
+
};
|
|
120937
|
+
const leaf = await issueLeaf(scratch, ca, identity, commonName, validDays);
|
|
120938
|
+
const chainPath = (0, node_path.join)(scratch, "chain.crt");
|
|
120939
|
+
await (0, node_fs_promises.writeFile)(chainPath, `${(0, node_fs.readFileSync)(leaf.certPath, "utf-8").trimEnd()}
|
|
120940
|
+
${(0, node_fs.readFileSync)(ca.caCertPath, "utf-8").trimEnd()}
|
|
120941
|
+
`, "utf-8");
|
|
120942
|
+
if (newCa) {
|
|
120943
|
+
await (0, node_fs_promises.copyFile)(ca.caCertPath, `${paths.caCertPath}.new`);
|
|
120944
|
+
await (0, node_fs_promises.copyFile)(ca.caKeyPath, `${paths.caKeyPath}.new`);
|
|
120945
|
+
(0, node_fs.renameSync)(`${paths.caCertPath}.new`, paths.caCertPath);
|
|
120946
|
+
(0, node_fs.renameSync)(`${paths.caKeyPath}.new`, paths.caKeyPath);
|
|
120947
|
+
await (0, node_fs_promises.chmod)(paths.caKeyPath, 384);
|
|
120948
|
+
}
|
|
120949
|
+
await (0, node_fs_promises.copyFile)(leaf.keyPath, `${paths.keyPath}.new`);
|
|
120950
|
+
await (0, node_fs_promises.copyFile)(chainPath, `${paths.certPath}.new`);
|
|
120951
|
+
(0, node_fs.renameSync)(`${paths.keyPath}.new`, paths.keyPath);
|
|
120952
|
+
(0, node_fs.renameSync)(`${paths.certPath}.new`, paths.certPath);
|
|
120953
|
+
await (0, node_fs_promises.chmod)(paths.keyPath, 384);
|
|
120954
|
+
} finally {
|
|
120955
|
+
await (0, node_fs_promises.rm)(scratch, {
|
|
120956
|
+
recursive: true,
|
|
120957
|
+
force: true
|
|
120958
|
+
});
|
|
120959
|
+
}
|
|
120960
|
+
}
|
|
120961
|
+
function describe(paths, generated, reason, caRotated, previousFingerprintSha256) {
|
|
120962
|
+
const leaf = new node_crypto.X509Certificate((0, node_fs.readFileSync)(paths.certPath));
|
|
120963
|
+
const ca = new node_crypto.X509Certificate((0, node_fs.readFileSync)(paths.caCertPath));
|
|
120964
|
+
const san = leaf.subjectAltName ?? "";
|
|
120965
|
+
return {
|
|
120966
|
+
...paths,
|
|
120967
|
+
generated,
|
|
120968
|
+
reason,
|
|
120969
|
+
caRotated,
|
|
120970
|
+
fingerprintSha256: leaf.fingerprint256,
|
|
120971
|
+
previousFingerprintSha256,
|
|
120972
|
+
caFingerprintSha256: ca.fingerprint256,
|
|
120973
|
+
validTo: new Date(leaf.validTo).toISOString(),
|
|
120974
|
+
sans: san === "" ? [] : san.split(", ")
|
|
120630
120975
|
};
|
|
120631
120976
|
}
|
|
120632
120977
|
function loadTlsCert(certPath, keyPath) {
|
|
@@ -198906,6 +199251,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
198906
199251
|
exports.AlertCenterAddon = require_builtins_alerts_alerts_addon.AlertCenterAddon;
|
|
198907
199252
|
exports.ApiKeyManager = require_builtins_local_auth_local_auth_addon.ApiKeyManager;
|
|
198908
199253
|
exports.AuthManager = require_builtins_local_auth_local_auth_addon.AuthManager;
|
|
199254
|
+
exports.CA_COMMON_NAME = CA_COMMON_NAME;
|
|
199255
|
+
exports.CA_VALIDITY_DAYS = CA_VALIDITY_DAYS;
|
|
198909
199256
|
exports.CLUSTER_SECRET_MISMATCH_TYPE = CLUSTER_SECRET_MISMATCH_TYPE;
|
|
198910
199257
|
exports.CLUSTER_SECRET_REJECTED_EXIT_CODE = CLUSTER_SECRET_REJECTED_EXIT_CODE;
|
|
198911
199258
|
exports.CORE_CAP_SERVICE_NAME = CORE_CAP_SERVICE_NAME;
|
|
@@ -198952,6 +199299,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
198952
199299
|
exports.INFRA_CAPABILITIES = INFRA_CAPABILITIES;
|
|
198953
199300
|
exports.IntegrationRegistry = IntegrationRegistry;
|
|
198954
199301
|
exports.JobJournal = JobJournal;
|
|
199302
|
+
exports.LEAF_RENEWAL_WINDOW_DAYS = LEAF_RENEWAL_WINDOW_DAYS;
|
|
198955
199303
|
exports.LifecycleJobEngine = LifecycleJobEngine;
|
|
198956
199304
|
exports.LifecycleStateMachine = LifecycleStateMachine;
|
|
198957
199305
|
exports.LivenessMonitorAddon = require_builtins_liveness_monitor_liveness_monitor_addon.LivenessMonitorAddon;
|
|
@@ -198962,6 +199310,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
198962
199310
|
exports.LogRingBuffer = LogRingBuffer;
|
|
198963
199311
|
exports.LokiDestination = require_builtins_loki_logging_index.LokiDestination$1;
|
|
198964
199312
|
exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
|
|
199313
|
+
exports.MAX_LEAF_VALIDITY_DAYS = MAX_LEAF_VALIDITY_DAYS;
|
|
198965
199314
|
exports.METHOD_ACCESS_MAP = require_dist10.METHOD_ACCESS_MAP;
|
|
198966
199315
|
exports.ModelDownloadService = require_file_data_plane.ModelDownloadService;
|
|
198967
199316
|
exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_python_deps.NATIVE_PROVIDER_SERVICE_INFIX;
|
|
@@ -198987,6 +199336,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
198987
199336
|
exports.ReadinessTimeoutError = require_dist10.ReadinessTimeoutError;
|
|
198988
199337
|
exports.ReplEngine = ReplEngine;
|
|
198989
199338
|
exports.RingBuffer = RingBuffer;
|
|
199339
|
+
exports.SERVER_AUTH_OID = SERVER_AUTH_OID;
|
|
198990
199340
|
exports.ScopedLogger = ScopedLogger;
|
|
198991
199341
|
exports.ScopedTokenManager = require_builtins_local_auth_local_auth_addon.ScopedTokenManager;
|
|
198992
199342
|
exports.SocketChannel = require_manifest_python_deps.SocketChannel;
|
|
@@ -199038,6 +199388,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
199038
199388
|
exports.clearPendingRestart = clearPendingRestart;
|
|
199039
199389
|
exports.clusterEventTopic = require_manifest_python_deps.clusterEventTopic;
|
|
199040
199390
|
exports.clusterSecretMatches = clusterSecretMatches;
|
|
199391
|
+
exports.collectCertIdentity = collectCertIdentity;
|
|
199041
199392
|
exports.collectModelFiles = require_file_data_plane.collectModelFiles;
|
|
199042
199393
|
exports.contentTypeFor = require_file_data_plane.contentTypeFor;
|
|
199043
199394
|
exports.copyDirRecursive = copyDirRecursive;
|
|
@@ -199104,6 +199455,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
199104
199455
|
}
|
|
199105
199456
|
});
|
|
199106
199457
|
exports.ensureTlsCert = ensureTlsCert;
|
|
199458
|
+
exports.evaluateExistingCert = evaluateExistingCert;
|
|
199107
199459
|
exports.expandCapMethods = require_dist10.expandCapMethods;
|
|
199108
199460
|
exports.fetchJson = require_file_data_plane.fetchJson;
|
|
199109
199461
|
Object.defineProperty(exports, "findInPath", {
|
|
@@ -237867,7 +238219,7 @@ var require_enums = __commonJS({
|
|
|
237867
238219
|
"../types/dist/enums.js"(exports) {
|
|
237868
238220
|
"use strict";
|
|
237869
238221
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
237870
|
-
var require_event_category =
|
|
238222
|
+
var require_event_category = require_event_category_EY0GNjV9();
|
|
237871
238223
|
var EventSourceType = /* @__PURE__ */ (function(EventSourceType2) {
|
|
237872
238224
|
EventSourceType2["Addon"] = "addon";
|
|
237873
238225
|
EventSourceType2["Core"] = "core";
|
|
@@ -237887,8 +238239,8 @@ var require_dist9 = __commonJS({
|
|
|
237887
238239
|
"../types/dist/index.js"(exports) {
|
|
237888
238240
|
"use strict";
|
|
237889
238241
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
237890
|
-
var require_event_category =
|
|
237891
|
-
var require_sleep =
|
|
238242
|
+
var require_event_category = require_event_category_EY0GNjV9();
|
|
238243
|
+
var require_sleep = require_sleep_C2XhJhkd();
|
|
237892
238244
|
var require_canonical_hash = require_canonical_hash_DNV8S5ET();
|
|
237893
238245
|
var require_enums2 = require_enums();
|
|
237894
238246
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
@@ -252258,6 +252610,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252258
252610
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
252259
252611
|
fetchedAt: zod.z.number()
|
|
252260
252612
|
});
|
|
252613
|
+
var INFERENCE_DEVICE_EXCLUSION_REASONS = [
|
|
252614
|
+
"disabled",
|
|
252615
|
+
"unavailable",
|
|
252616
|
+
"cannot-host-camera-root",
|
|
252617
|
+
"accelerator-preferred"
|
|
252618
|
+
];
|
|
252619
|
+
var InferenceDeviceExclusionReasonSchema = zod.z.enum(INFERENCE_DEVICE_EXCLUSION_REASONS);
|
|
252261
252620
|
var NodeInferenceDeviceSchema = zod.z.object({
|
|
252262
252621
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
252263
252622
|
key: zod.z.string(),
|
|
@@ -252288,7 +252647,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252288
252647
|
* available per format; this is the stored selection that becomes the
|
|
252289
252648
|
* default for EVERY camera landing on this accelerator.
|
|
252290
252649
|
*/
|
|
252291
|
-
steps: zod.z.record(zod.z.string(), DeviceStepConfigSchema).optional()
|
|
252650
|
+
steps: zod.z.record(zod.z.string(), DeviceStepConfigSchema).optional(),
|
|
252651
|
+
/**
|
|
252652
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
252653
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
252654
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
252655
|
+
* never disagree with the election — deriving it in the UI from
|
|
252656
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
252657
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
252658
|
+
* "an accelerator is serving" predicate).
|
|
252659
|
+
*/
|
|
252660
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
252292
252661
|
});
|
|
252293
252662
|
var NodeInferenceDevicesSchema = zod.z.object({
|
|
252294
252663
|
nodeId: zod.z.string(),
|
|
@@ -257320,7 +257689,35 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
257320
257689
|
*/
|
|
257321
257690
|
priority: zod.z.number()
|
|
257322
257691
|
});
|
|
257323
|
-
var
|
|
257692
|
+
var LocalPortSourceEnum = zod.z.enum([
|
|
257693
|
+
"server-config",
|
|
257694
|
+
"server-env",
|
|
257695
|
+
"caller-hint",
|
|
257696
|
+
"default"
|
|
257697
|
+
]);
|
|
257698
|
+
var AdvertisedLocalPortSchema = zod.z.object({
|
|
257699
|
+
port: zod.z.number().int().min(1).max(65535),
|
|
257700
|
+
source: LocalPortSourceEnum
|
|
257701
|
+
});
|
|
257702
|
+
var GetConnectionEndpointsResultSchema = zod.z.object({
|
|
257703
|
+
endpoints: zod.z.array(ConnectionEndpointSchema).readonly(),
|
|
257704
|
+
/**
|
|
257705
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
257706
|
+
* came from.
|
|
257707
|
+
*
|
|
257708
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
257709
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
257710
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
257711
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
257712
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
257713
|
+
* `caller-hint` is the hub's own socket.
|
|
257714
|
+
*
|
|
257715
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
257716
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
257717
|
+
* `caller-hint`.
|
|
257718
|
+
*/
|
|
257719
|
+
localPort: AdvertisedLocalPortSchema
|
|
257720
|
+
});
|
|
257324
257721
|
var NotificationEndpointSchema = zod.z.object({
|
|
257325
257722
|
/** The operator's explicit choice, or null for AUTO. */
|
|
257326
257723
|
baseUrl: zod.z.string().nullable(),
|
|
@@ -257362,10 +257759,35 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
257362
257759
|
* Honours `getAllowedAddresses()` when set — addresses outside
|
|
257363
257760
|
* the allowlist are dropped (the public tunnel + loopback are
|
|
257364
257761
|
* always included as escape hatches).
|
|
257762
|
+
*
|
|
257763
|
+
* **The port is the hub's, not the caller's** (D62 — a function's fact
|
|
257764
|
+
* belongs to whoever already owns it). This method used to take a `port`
|
|
257765
|
+
* and echo it onto every LAN and loopback URL it advertised, which made
|
|
257766
|
+
* every client a second authority on a socket only the hub binds. A viewer
|
|
257767
|
+
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
257768
|
+
* infers 443 from the scheme, asks with 443, and was handed
|
|
257769
|
+
* `https://192.168.1.9:443` for a hub listening on 4443. That candidate
|
|
257770
|
+
* cannot ever answer, and losing its race reads in the log exactly like
|
|
257771
|
+
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
257772
|
+
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
257773
|
+
* dead on every single connect.
|
|
257774
|
+
*
|
|
257775
|
+
* The hub now resolves its own listen port and reports it as `localPort`,
|
|
257776
|
+
* with the SOURCE of the number, so a client can tell a fact from an echo.
|
|
257777
|
+
*
|
|
257778
|
+
* Out of scope on purpose: a LAN URL that is not the hub's own socket (a
|
|
257779
|
+
* reverse proxy in front of it on another port) is not this method's to
|
|
257780
|
+
* invent either — pin it with `setNotificationEndpoint` / a configured
|
|
257781
|
+
* origin, which is an operator statement rather than a guess.
|
|
257365
257782
|
*/
|
|
257366
257783
|
getConnectionEndpoints: require_sleep.method(zod.z.object({
|
|
257367
|
-
/**
|
|
257368
|
-
|
|
257784
|
+
/**
|
|
257785
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
257786
|
+
* written against the echoing contract keep working; the hub uses it
|
|
257787
|
+
* only when it cannot read its own port, and says so via
|
|
257788
|
+
* `localPort.source === 'caller-hint'`.
|
|
257789
|
+
*/
|
|
257790
|
+
port: zod.z.number().int().min(1).max(65535).optional(),
|
|
257369
257791
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
257370
257792
|
* candidate. Default `true`. */
|
|
257371
257793
|
includeLoopback: zod.z.boolean().optional(),
|
|
@@ -263609,10 +264031,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
263609
264031
|
} };
|
|
263610
264032
|
}
|
|
263611
264033
|
var LAST_FETCHED_FIELD = "lastFetchedAt";
|
|
264034
|
+
var RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS = 6e4;
|
|
264035
|
+
var OPERATOR_WRITTEN_STALE_MS = 10 * 6e4;
|
|
263612
264036
|
function createRuntimeStateBridge(params) {
|
|
263613
264037
|
const { runtimeState, cap, ownDeviceId, refresh, staleMs, empty, logger } = params;
|
|
263614
264038
|
const missCooldownMs = params.refreshMissCooldownMs ?? 6e4;
|
|
264039
|
+
const staleRead = params.staleRead ?? "await-refresh";
|
|
263615
264040
|
let missCooldownUntil = 0;
|
|
264041
|
+
let refreshInFlight = null;
|
|
263616
264042
|
const readFetchedAt = () => {
|
|
263617
264043
|
const value = runtimeState.getCapState(cap.name)?.[LAST_FETCHED_FIELD];
|
|
263618
264044
|
return typeof value === "number" ? value : 0;
|
|
@@ -263627,14 +264053,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
263627
264053
|
}
|
|
263628
264054
|
});
|
|
263629
264055
|
};
|
|
263630
|
-
const
|
|
263631
|
-
const slice = runtimeState.getCapState(cap.name);
|
|
263632
|
-
const fetchedAt = readFetchedAt();
|
|
263633
|
-
if (slice && Date.now() - fetchedAt <= staleMs) {
|
|
263634
|
-
missCooldownUntil = 0;
|
|
263635
|
-
return;
|
|
263636
|
-
}
|
|
263637
|
-
if (Date.now() < missCooldownUntil) return;
|
|
264056
|
+
const runRefresh = async (fetchedAt) => {
|
|
263638
264057
|
try {
|
|
263639
264058
|
await refresh();
|
|
263640
264059
|
} catch (err) {
|
|
@@ -263650,6 +264069,34 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
263650
264069
|
}
|
|
263651
264070
|
openMissCooldown(void 0);
|
|
263652
264071
|
};
|
|
264072
|
+
const startRefresh = (fetchedAt) => {
|
|
264073
|
+
const existing = refreshInFlight;
|
|
264074
|
+
if (existing !== null) return existing;
|
|
264075
|
+
const started = runRefresh(fetchedAt).catch(() => void 0).finally(() => {
|
|
264076
|
+
refreshInFlight = null;
|
|
264077
|
+
});
|
|
264078
|
+
refreshInFlight = started;
|
|
264079
|
+
return started;
|
|
264080
|
+
};
|
|
264081
|
+
const ensureFresh = async () => {
|
|
264082
|
+
const slice = runtimeState.getCapState(cap.name);
|
|
264083
|
+
const fetchedAt = readFetchedAt();
|
|
264084
|
+
if (slice && Date.now() - fetchedAt <= staleMs) {
|
|
264085
|
+
missCooldownUntil = 0;
|
|
264086
|
+
return;
|
|
264087
|
+
}
|
|
264088
|
+
if (Date.now() < missCooldownUntil) return;
|
|
264089
|
+
if (staleRead === "serve-and-revalidate") {
|
|
264090
|
+
if (refreshInFlight !== null) return;
|
|
264091
|
+
if (slice && fetchedAt > 0) {
|
|
264092
|
+
startRefresh(fetchedAt);
|
|
264093
|
+
return;
|
|
264094
|
+
}
|
|
264095
|
+
await startRefresh(fetchedAt);
|
|
264096
|
+
return;
|
|
264097
|
+
}
|
|
264098
|
+
await runRefresh(fetchedAt);
|
|
264099
|
+
};
|
|
263653
264100
|
const projectStatus = () => {
|
|
263654
264101
|
const slice = runtimeState.getCapState(cap.name);
|
|
263655
264102
|
if (!slice) return empty();
|
|
@@ -277087,6 +277534,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
277087
277534
|
exports.HumidifierStatusSchema = HumidifierStatusSchema;
|
|
277088
277535
|
exports.HumiditySensorStatusSchema = HumiditySensorStatusSchema;
|
|
277089
277536
|
exports.HvacModeSchema = HvacModeSchema;
|
|
277537
|
+
exports.INFERENCE_DEVICE_EXCLUSION_REASONS = INFERENCE_DEVICE_EXCLUSION_REASONS;
|
|
277090
277538
|
exports.ImageContractSchema = ImageContractSchema;
|
|
277091
277539
|
exports.ImageContractStateSchema = ImageContractStateSchema;
|
|
277092
277540
|
exports.ImageRotateSchema = ImageRotateSchema;
|
|
@@ -277094,6 +277542,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
277094
277542
|
exports.ImageSettingsPatchSchema = ImageSettingsPatchSchema;
|
|
277095
277543
|
exports.ImageSettingsStatusSchema = ImageSettingsStatusSchema;
|
|
277096
277544
|
exports.ImageStatusSchema = ImageStatusSchema;
|
|
277545
|
+
exports.InferenceDeviceExclusionReasonSchema = InferenceDeviceExclusionReasonSchema;
|
|
277097
277546
|
exports.IngestOwnerSchema = IngestOwnerSchema;
|
|
277098
277547
|
exports.InstalledPackageSchema = InstalledPackageSchema;
|
|
277099
277548
|
exports.IntegrationLiteSchema = IntegrationLiteSchema;
|
|
@@ -277306,6 +277755,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
277306
277755
|
exports.NotificationSchema = NotificationSchema;
|
|
277307
277756
|
exports.NotifierStatusSchema = NotifierStatusSchema;
|
|
277308
277757
|
exports.NumericSensorStatusSchema = NumericSensorStatusSchema;
|
|
277758
|
+
exports.OPERATOR_WRITTEN_STALE_MS = OPERATOR_WRITTEN_STALE_MS;
|
|
277309
277759
|
exports.OPS_LOG_DEFAULT_LIMIT = OPS_LOG_DEFAULT_LIMIT;
|
|
277310
277760
|
exports.OPS_LOG_RING_DEFAULT_MAX = OPS_LOG_RING_DEFAULT_MAX;
|
|
277311
277761
|
exports.OauthIntegrationDescriptorSchema = OauthIntegrationDescriptorSchema;
|
|
@@ -277388,6 +277838,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
277388
277838
|
exports.RESTORED_CAP_NAMES = RESTORED_CAP_NAMES;
|
|
277389
277839
|
exports.RUNTIME_DEFAULTS = RUNTIME_DEFAULTS;
|
|
277390
277840
|
exports.RUNTIME_STATE_POLICY = RUNTIME_STATE_POLICY;
|
|
277841
|
+
exports.RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS = RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS;
|
|
277391
277842
|
exports.RUNTIME_TO_FORMAT = RUNTIME_TO_FORMAT;
|
|
277392
277843
|
exports.RawStateResultSchema = require_sleep.RawStateResultSchema;
|
|
277393
277844
|
exports.ReadGopBytesResultSchema = ReadGopBytesResultSchema;
|
|
@@ -399226,7 +399677,7 @@ var require_post_boot_service = __commonJS({
|
|
|
399226
399677
|
return entry.payload;
|
|
399227
399678
|
}
|
|
399228
399679
|
async run(context) {
|
|
399229
|
-
const { port, host, dataPath, trpcRegistered } = context;
|
|
399680
|
+
const { port, host, dataPath, trpcRegistered, tlsCert } = context;
|
|
399230
399681
|
this.eventBus.emit({
|
|
399231
399682
|
id: (0, node_crypto_1.randomUUID)(),
|
|
399232
399683
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -399235,6 +399686,7 @@ var require_post_boot_service = __commonJS({
|
|
|
399235
399686
|
data: { port, host, trpcRegistered, dataPath }
|
|
399236
399687
|
});
|
|
399237
399688
|
this.emitRestartCompletedIfPending(dataPath);
|
|
399689
|
+
this.emitTlsCertChangedIfReissued(tlsCert);
|
|
399238
399690
|
await this.reconcileLifecycleJobsIfAny();
|
|
399239
399691
|
}
|
|
399240
399692
|
async reconcileLifecycleJobsIfAny() {
|
|
@@ -399243,6 +399695,27 @@ var require_post_boot_service = __commonJS({
|
|
|
399243
399695
|
this.logger.info("Lifecycle jobs reconciled at boot", { meta: { resumed, failed } });
|
|
399244
399696
|
}
|
|
399245
399697
|
}
|
|
399698
|
+
emitTlsCertChangedIfReissued(tlsCert) {
|
|
399699
|
+
if (tlsCert === void 0 || !tlsCert.generated)
|
|
399700
|
+
return;
|
|
399701
|
+
const payload = {
|
|
399702
|
+
reason: tlsCert.reason ?? "unknown",
|
|
399703
|
+
fingerprintSha256: tlsCert.fingerprintSha256,
|
|
399704
|
+
caFingerprintSha256: tlsCert.caFingerprintSha256,
|
|
399705
|
+
caRotated: tlsCert.caRotated,
|
|
399706
|
+
caCertPath: tlsCert.caCertPath,
|
|
399707
|
+
validTo: tlsCert.validTo,
|
|
399708
|
+
sans: tlsCert.sans
|
|
399709
|
+
};
|
|
399710
|
+
this.logger.warn("TLS certificate reissued", { meta: payload });
|
|
399711
|
+
this.eventBus.emit({
|
|
399712
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
399713
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
399714
|
+
source: { type: "core", id: "system" },
|
|
399715
|
+
category: types_1.EventCategory.SystemTlsCertChanged,
|
|
399716
|
+
data: payload
|
|
399717
|
+
});
|
|
399718
|
+
}
|
|
399246
399719
|
emitRestartCompletedIfPending(dataDir) {
|
|
399247
399720
|
const marker = (0, system_1.readPendingRestart)(dataDir);
|
|
399248
399721
|
if (marker === null)
|
|
@@ -401812,11 +402285,11 @@ var require_boot_config = __commonJS({
|
|
|
401812
402285
|
exports.loadBootstrapConfig = loadBootstrapConfig;
|
|
401813
402286
|
exports.autoGenerateJwtSecret = autoGenerateJwtSecret;
|
|
401814
402287
|
exports.setupInfra = setupInfra;
|
|
402288
|
+
var node_crypto_1 = __require("crypto");
|
|
401815
402289
|
var fs = __importStar(__require("fs"));
|
|
401816
402290
|
var path = __importStar(__require("path"));
|
|
401817
|
-
var yaml = __importStar(require_js_yaml());
|
|
401818
|
-
var node_crypto_1 = __require("crypto");
|
|
401819
402291
|
var types_1 = require_dist9();
|
|
402292
|
+
var yaml = __importStar(require_js_yaml());
|
|
401820
402293
|
var config_schema_1 = require_config_schema();
|
|
401821
402294
|
var storage_location_manager_1 = require_storage_location_manager();
|
|
401822
402295
|
var CONFIG_DEFAULTS = {
|
|
@@ -401936,6 +402409,7 @@ var require_boot_config = __commonJS({
|
|
|
401936
402409
|
console.log(`[Phase2] Location "${name}": ${available ? "OK" : "UNAVAILABLE"} \u2192 ${locPath}`);
|
|
401937
402410
|
}
|
|
401938
402411
|
let tlsOptions;
|
|
402412
|
+
let tlsCert;
|
|
401939
402413
|
if (config.tls.enabled) {
|
|
401940
402414
|
const core = require_dist3();
|
|
401941
402415
|
const { ensureTlsCert, loadTlsCert } = core;
|
|
@@ -401945,11 +402419,8 @@ var require_boot_config = __commonJS({
|
|
|
401945
402419
|
tlsOptions = { key: pair.key, cert: pair.cert };
|
|
401946
402420
|
} else {
|
|
401947
402421
|
const tlsResult = await ensureTlsCert(dataPath);
|
|
401948
|
-
|
|
401949
|
-
|
|
401950
|
-
} else {
|
|
401951
|
-
console.log(`[Phase2c] Using existing TLS cert at ${tlsResult.certPath}`);
|
|
401952
|
-
}
|
|
402422
|
+
tlsCert = tlsResult;
|
|
402423
|
+
logTlsCert(tlsResult);
|
|
401953
402424
|
const pair = loadTlsCert(tlsResult.certPath, tlsResult.keyPath);
|
|
401954
402425
|
tlsOptions = { key: pair.key, cert: pair.cert };
|
|
401955
402426
|
}
|
|
@@ -401958,9 +402429,20 @@ var require_boot_config = __commonJS({
|
|
|
401958
402429
|
bootstrapConfig: config,
|
|
401959
402430
|
dataPath,
|
|
401960
402431
|
locationManager,
|
|
401961
|
-
tlsOptions
|
|
402432
|
+
tlsOptions,
|
|
402433
|
+
tlsCert
|
|
401962
402434
|
};
|
|
401963
402435
|
}
|
|
402436
|
+
function logTlsCert(result) {
|
|
402437
|
+
if (!result.generated) {
|
|
402438
|
+
console.log(`[Phase2c] TLS cert unchanged \u2014 ${result.certPath} (leaf ${result.fingerprintSha256}, valid to ${result.validTo})`);
|
|
402439
|
+
return;
|
|
402440
|
+
}
|
|
402441
|
+
console.log(`[Phase2c] TLS CERTIFICATE REISSUED \u2014 reason=${result.reason}, caRotated=${result.caRotated}`);
|
|
402442
|
+
console.log(`[Phase2c] leaf ${result.previousFingerprintSha256 ?? "(none)"} \u2192 ${result.fingerprintSha256}`);
|
|
402443
|
+
console.log(`[Phase2c] valid to ${result.validTo}, names: ${result.sans.join(", ")}`);
|
|
402444
|
+
console.log(result.caRotated ? `[Phase2c] ACTION REQUIRED: the local CA changed. Install ${result.caCertPath} (SHA-256 ${result.caFingerprintSha256}) on every device that trusted the previous certificate.` : `[Phase2c] Local CA unchanged (${result.caFingerprintSha256}) \u2014 devices that trust ${result.caCertPath} keep working.`);
|
|
402445
|
+
}
|
|
401964
402446
|
}
|
|
401965
402447
|
});
|
|
401966
402448
|
|
|
@@ -409443,7 +409925,7 @@ var require_main4 = __commonJS({
|
|
|
409443
409925
|
const configPath = process.env.CONFIG_PATH ?? path.join(process.env.CAMSTACK_DATA ?? path.join(process.cwd(), "camstack-data"), "config.yaml");
|
|
409444
409926
|
const bootstrapConfig = (0, boot_config_1.loadBootstrapConfig)(configPath);
|
|
409445
409927
|
const infra = await (0, boot_config_1.setupInfra)(configPath, bootstrapConfig);
|
|
409446
|
-
const { dataPath, tlsOptions } = infra;
|
|
409928
|
+
const { dataPath, tlsOptions, tlsCert } = infra;
|
|
409447
409929
|
const port = infra.bootstrapConfig.server.port;
|
|
409448
409930
|
const host = infra.bootstrapConfig.server.host;
|
|
409449
409931
|
const fastifyOpts = tlsOptions ? { https: tlsOptions } : {};
|
|
@@ -410192,7 +410674,7 @@ var require_main4 = __commonJS({
|
|
|
410192
410674
|
logger.info("CamStack server listening", { meta: { protocol, host, port, trpcRegistered } });
|
|
410193
410675
|
void Promise.all([resolveAdminUi(), resolveViewerUi()]);
|
|
410194
410676
|
const postBoot = app.get(post_boot_service_1.PostBootService);
|
|
410195
|
-
await postBoot.run({ port, host, dataPath, trpcRegistered });
|
|
410677
|
+
await postBoot.run({ port, host, dataPath, trpcRegistered, tlsCert });
|
|
410196
410678
|
try {
|
|
410197
410679
|
const confirm = app.get(server_update_service_1.ServerUpdateService).confirmBootHealthy();
|
|
410198
410680
|
if (confirm.promoted !== null) {
|