camstack 1.2.51 → 1.2.53
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-C9C8EoK8.mjs
|
|
14526
14526
|
var WELL_KNOWN_TABS = [
|
|
14527
14527
|
{
|
|
14528
14528
|
id: "overview",
|
|
@@ -17070,6 +17070,10 @@ var addonSettingsCapability = {
|
|
|
17070
17070
|
kind: "mutation",
|
|
17071
17071
|
auth: "admin"
|
|
17072
17072
|
}),
|
|
17073
|
+
getIntegrationSettings: method(external_exports.object({
|
|
17074
|
+
addonId: external_exports.string(),
|
|
17075
|
+
nodeId: external_exports.string().optional()
|
|
17076
|
+
}), SettingsSchemaWithValuesSchema.nullable()),
|
|
17073
17077
|
getDeviceSettings: method(external_exports.object({
|
|
17074
17078
|
addonId: external_exports.string(),
|
|
17075
17079
|
deviceId: external_exports.number(),
|
|
@@ -38487,6 +38491,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
38487
38491
|
addonId: null,
|
|
38488
38492
|
access: "view"
|
|
38489
38493
|
},
|
|
38494
|
+
"addonSettings.getIntegrationSettings": {
|
|
38495
|
+
capName: "addon-settings",
|
|
38496
|
+
capScope: "system",
|
|
38497
|
+
addonId: null,
|
|
38498
|
+
access: "view"
|
|
38499
|
+
},
|
|
38490
38500
|
"addonSettings.updateDeviceSettings": {
|
|
38491
38501
|
capName: "addon-settings",
|
|
38492
38502
|
capScope: "system",
|
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-P6IF6IX5.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-3YAJ644E.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-3YAJ644E.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-255INDLH.js");
|
|
1134
1134
|
if (presetNamespace) {
|
|
1135
1135
|
const spinner4 = clack.spinner();
|
|
1136
1136
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-DdEXjTDo.js
|
|
23637
|
+
var require_dist_DdEXjTDo = __commonJS({
|
|
23638
|
+
"../system/dist/dist-DdEXjTDo.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -24231,6 +24231,40 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
24231
24231
|
deviceSettingsSchema() {
|
|
24232
24232
|
return null;
|
|
24233
24233
|
}
|
|
24234
|
+
/**
|
|
24235
|
+
* INTEGRATION-LEVEL SETTINGS — declare which of this addon's global sections
|
|
24236
|
+
* ARE the configuration of its integration.
|
|
24237
|
+
*
|
|
24238
|
+
* Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
|
|
24239
|
+
* operator should find on the addon's integration page (System →
|
|
24240
|
+
* Integrations → <name>) rather than only in the cluster-wide list of every
|
|
24241
|
+
* addon. Empty (the default) means the addon has no integration-level
|
|
24242
|
+
* settings and no such surface is offered — this is opt-in, because whether
|
|
24243
|
+
* an addon's configuration IS its integration's configuration depends on the
|
|
24244
|
+
* nature of the integration.
|
|
24245
|
+
*
|
|
24246
|
+
* WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
|
|
24247
|
+
* the ONE global schema, in the ONE addon store, written by the ONE
|
|
24248
|
+
* `updateGlobalSettings` path. There is deliberately no
|
|
24249
|
+
* `updateIntegrationSettings`: a second write path is how a surface acquires
|
|
24250
|
+
* a second store key, and this repo has shipped that twice (`btmPath@hub`,
|
|
24251
|
+
* D266). Selecting sections cannot introduce a key that selecting cannot.
|
|
24252
|
+
*
|
|
24253
|
+
* WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
|
|
24254
|
+
* `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
|
|
24255
|
+
* removed with the reason recorded at
|
|
24256
|
+
* `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
|
|
24257
|
+
* determined by WHICH schema it lives in, not by a field-level marker."* A
|
|
24258
|
+
* marker sprinkled across sections also has to borrow a field that already
|
|
24259
|
+
* means something else; borrowing `section.tab` put the literal word
|
|
24260
|
+
* "integration" into an operator-facing tab bar, because `tab` means "how to
|
|
24261
|
+
* GROUP this visually" and cannot also mean "where this lives" (D269
|
|
24262
|
+
* supersedes D268). One declaration, in one place, next to the schema whose
|
|
24263
|
+
* ids it names.
|
|
24264
|
+
*/
|
|
24265
|
+
integrationSettingSections() {
|
|
24266
|
+
return [];
|
|
24267
|
+
}
|
|
24234
24268
|
async getGlobalSettings(overlay, cap, nodeId) {
|
|
24235
24269
|
const schema = this.globalSettingsSchema(cap);
|
|
24236
24270
|
if (!schema) return { sections: [] };
|
|
@@ -24241,6 +24275,55 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
24241
24275
|
} : projected);
|
|
24242
24276
|
}
|
|
24243
24277
|
/**
|
|
24278
|
+
* The integration-level view of this addon's settings: exactly the sections
|
|
24279
|
+
* named by {@link integrationSettingSections}, hydrated from the SAME store
|
|
24280
|
+
* `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
|
|
24281
|
+
*
|
|
24282
|
+
* Returns `null` when the addon declared nothing — an addon that opts out has
|
|
24283
|
+
* no integration settings surface at all, rather than an empty one that reads
|
|
24284
|
+
* as a failed load.
|
|
24285
|
+
*
|
|
24286
|
+
* Three properties hold BY CONSTRUCTION, which is why they are here in core
|
|
24287
|
+
* and not in whichever UI happens to render this:
|
|
24288
|
+
*
|
|
24289
|
+
* 1. **One key.** The payload is a SUBSET of the global schema, so a field
|
|
24290
|
+
* shown here is the same field, with the same bare key, that the addon's
|
|
24291
|
+
* own page shows. There is no integration-specific writer — callers save
|
|
24292
|
+
* through `updateGlobalSettings` — so a second store key is unreachable,
|
|
24293
|
+
* not merely discouraged.
|
|
24294
|
+
* 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
|
|
24295
|
+
* is `<key>@<nodeId>` and an integration is not a node; whichever node
|
|
24296
|
+
* such a field silently picked would be a wrong answer for the operator
|
|
24297
|
+
* who opened the page (D266).
|
|
24298
|
+
* 3. **No silent typo.** A declared id that names no section throws. The
|
|
24299
|
+
* alternative — skip it — turns a rename into a surface that quietly
|
|
24300
|
+
* empties, which looks exactly like an addon with nothing to configure.
|
|
24301
|
+
*/
|
|
24302
|
+
async getIntegrationSettings(nodeId) {
|
|
24303
|
+
const declared = this.integrationSettingSections();
|
|
24304
|
+
if (declared.length === 0) return null;
|
|
24305
|
+
const schema = this.globalSettingsSchema();
|
|
24306
|
+
if (!schema) throw new Error(`${this.constructor.name}: integrationSettingSections() names [${declared.join(", ")}] but globalSettingsSchema() returns null.`);
|
|
24307
|
+
const byId = new Map(schema.sections.map((section) => [section.id, section]));
|
|
24308
|
+
const sections = [];
|
|
24309
|
+
for (const id of declared) {
|
|
24310
|
+
const section = byId.get(id);
|
|
24311
|
+
if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
|
|
24312
|
+
const fields = dropPerNodeFields(section.fields);
|
|
24313
|
+
if (fields.length === 0) continue;
|
|
24314
|
+
sections.push({
|
|
24315
|
+
...section,
|
|
24316
|
+
fields
|
|
24317
|
+
});
|
|
24318
|
+
}
|
|
24319
|
+
if (sections.length === 0) return null;
|
|
24320
|
+
const projected = await this.resolveGlobalStore(nodeId);
|
|
24321
|
+
return hydrateSchema({
|
|
24322
|
+
...schema,
|
|
24323
|
+
sections
|
|
24324
|
+
}, projected);
|
|
24325
|
+
}
|
|
24326
|
+
/**
|
|
24244
24327
|
* The raw addon store PROJECTED onto the target node's bare per-node keys:
|
|
24245
24328
|
* every `perNode: true` field carries THAT node's scoped value on its bare
|
|
24246
24329
|
* key (absent scoped key ⇒ key absent, so the schema `default` wins — no
|
|
@@ -24540,6 +24623,33 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
24540
24623
|
return {};
|
|
24541
24624
|
}
|
|
24542
24625
|
};
|
|
24626
|
+
function dropPerNodeFields(fields) {
|
|
24627
|
+
const kept = [];
|
|
24628
|
+
for (const field of fields) {
|
|
24629
|
+
if (field.type === "group") {
|
|
24630
|
+
const inner = dropPerNodeFields(field.fields);
|
|
24631
|
+
if (inner.length > 0) kept.push({
|
|
24632
|
+
...field,
|
|
24633
|
+
fields: inner
|
|
24634
|
+
});
|
|
24635
|
+
continue;
|
|
24636
|
+
}
|
|
24637
|
+
if (field.type === "sub-tabs") {
|
|
24638
|
+
const tabs = field.tabs.map((tab) => ({
|
|
24639
|
+
...tab,
|
|
24640
|
+
fields: dropPerNodeFields(tab.fields)
|
|
24641
|
+
})).filter((tab) => tab.fields.length > 0);
|
|
24642
|
+
if (tabs.length > 0) kept.push({
|
|
24643
|
+
...field,
|
|
24644
|
+
tabs
|
|
24645
|
+
});
|
|
24646
|
+
continue;
|
|
24647
|
+
}
|
|
24648
|
+
if ("perNode" in field && field.perNode === true) continue;
|
|
24649
|
+
kept.push(field);
|
|
24650
|
+
}
|
|
24651
|
+
return kept;
|
|
24652
|
+
}
|
|
24543
24653
|
function collectPerNodeFieldKeys(fields) {
|
|
24544
24654
|
const collected = [];
|
|
24545
24655
|
for (const field of fields) {
|
|
@@ -27528,6 +27638,10 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
27528
27638
|
kind: "mutation",
|
|
27529
27639
|
auth: "admin"
|
|
27530
27640
|
}),
|
|
27641
|
+
getIntegrationSettings: method(zod.z.object({
|
|
27642
|
+
addonId: zod.z.string(),
|
|
27643
|
+
nodeId: zod.z.string().optional()
|
|
27644
|
+
}), SettingsSchemaWithValuesSchema.nullable()),
|
|
27531
27645
|
getDeviceSettings: method(zod.z.object({
|
|
27532
27646
|
addonId: zod.z.string(),
|
|
27533
27647
|
deviceId: zod.z.number(),
|
|
@@ -48902,7 +49016,7 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
48902
49016
|
"ffmpeg.binaryPath": "ffmpeg",
|
|
48903
49017
|
"ffmpeg.hwAccel": "auto",
|
|
48904
49018
|
"ffmpeg.threadCount": 0,
|
|
48905
|
-
"auth.tokenExpiry": "
|
|
49019
|
+
"auth.tokenExpiry": "30d"
|
|
48906
49020
|
};
|
|
48907
49021
|
var AccessoryKind = {
|
|
48908
49022
|
Siren: DeviceRole.Siren,
|
|
@@ -49658,6 +49772,12 @@ var require_dist_Dl6MFXPr = __commonJS({
|
|
|
49658
49772
|
addonId: null,
|
|
49659
49773
|
access: "view"
|
|
49660
49774
|
},
|
|
49775
|
+
"addonSettings.getIntegrationSettings": {
|
|
49776
|
+
capName: "addon-settings",
|
|
49777
|
+
capScope: "system",
|
|
49778
|
+
addonId: null,
|
|
49779
|
+
access: "view"
|
|
49780
|
+
},
|
|
49661
49781
|
"addonSettings.updateDeviceSettings": {
|
|
49662
49782
|
capName: "addon-settings",
|
|
49663
49783
|
capScope: "system",
|
|
@@ -58395,7 +58515,7 @@ var require_alerts_addon = __commonJS({
|
|
|
58395
58515
|
[Symbol.toStringTag]: { value: "Module" }
|
|
58396
58516
|
});
|
|
58397
58517
|
require_chunk_Cek0wNdY();
|
|
58398
|
-
var require_dist10 =
|
|
58518
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
58399
58519
|
function selectExpired(alerts, cutoffMs) {
|
|
58400
58520
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
58401
58521
|
}
|
|
@@ -59214,7 +59334,7 @@ var require_console_logging = __commonJS({
|
|
|
59214
59334
|
[Symbol.toStringTag]: { value: "Module" }
|
|
59215
59335
|
});
|
|
59216
59336
|
require_chunk_Cek0wNdY();
|
|
59217
|
-
var require_dist10 =
|
|
59337
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
59218
59338
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
59219
59339
|
var LEVEL_RANK = {
|
|
59220
59340
|
debug: 0,
|
|
@@ -59308,7 +59428,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
59308
59428
|
"use strict";
|
|
59309
59429
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
59310
59430
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
59311
|
-
var require_dist10 =
|
|
59431
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
59312
59432
|
var node_crypto = __require("crypto");
|
|
59313
59433
|
var node_fs_promises = __require("fs/promises");
|
|
59314
59434
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -60205,28 +60325,88 @@ var require_core_blocks = __commonJS({
|
|
|
60205
60325
|
}
|
|
60206
60326
|
});
|
|
60207
60327
|
|
|
60208
|
-
// ../system/dist/retired-settings-keys-
|
|
60209
|
-
var
|
|
60210
|
-
"../system/dist/retired-settings-keys-
|
|
60328
|
+
// ../system/dist/retired-settings-keys-BXaTgLyZ.js
|
|
60329
|
+
var require_retired_settings_keys_BXaTgLyZ = __commonJS({
|
|
60330
|
+
"../system/dist/retired-settings-keys-BXaTgLyZ.js"(exports) {
|
|
60211
60331
|
"use strict";
|
|
60212
|
-
var require_dist10 =
|
|
60332
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
60213
60333
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
60214
60334
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
60215
60335
|
return raw === "" || raw === "hub";
|
|
60216
60336
|
}
|
|
60217
|
-
var RETIRED_SETTINGS_KEYS = [
|
|
60218
|
-
|
|
60219
|
-
|
|
60220
|
-
|
|
60221
|
-
|
|
60222
|
-
|
|
60223
|
-
|
|
60224
|
-
|
|
60225
|
-
|
|
60226
|
-
|
|
60227
|
-
|
|
60228
|
-
|
|
60229
|
-
|
|
60337
|
+
var RETIRED_SETTINGS_KEYS = [
|
|
60338
|
+
{
|
|
60339
|
+
namespace: "detection-pipeline",
|
|
60340
|
+
collection: "addon-settings",
|
|
60341
|
+
row: "root",
|
|
60342
|
+
keys: ["pipelineSteps", "pipelineEngine"],
|
|
60343
|
+
perNodeKeys: [
|
|
60344
|
+
"engineRuntime",
|
|
60345
|
+
"engineBackend",
|
|
60346
|
+
"engineDevice",
|
|
60347
|
+
"probedBestEngine"
|
|
60348
|
+
],
|
|
60349
|
+
reason: "global step/engine seed and the per-node engine cascade \u2014 both removed; the live per-camera dispatch path never read either"
|
|
60350
|
+
},
|
|
60351
|
+
{
|
|
60352
|
+
namespace: "pipeline-orchestrator",
|
|
60353
|
+
collection: "addon-settings",
|
|
60354
|
+
row: "root",
|
|
60355
|
+
keys: [
|
|
60356
|
+
"enabledNodes",
|
|
60357
|
+
"enabledDecoderNodes",
|
|
60358
|
+
"enabledAudioNodes",
|
|
60359
|
+
"remoteSourcingNodes",
|
|
60360
|
+
"nativeLeaseTtlMs"
|
|
60361
|
+
],
|
|
60362
|
+
perNodeKeys: ["backend"],
|
|
60363
|
+
reason: 'the pre-singleton "enabled nodes" role model (node capability now lives per node in agent-settings and is derived by NodeTopology.refresh, never read from this row), `nativeLeaseTtlMs` superseded by `nativeLeaseActivityMs`, and the decoder `backend` selector whose resolver returns DEFAULT_DECODER_BACKEND unconditionally (decoder-backend.ts)'
|
|
60364
|
+
},
|
|
60365
|
+
{
|
|
60366
|
+
namespace: "stream-broker",
|
|
60367
|
+
collection: "addon-settings",
|
|
60368
|
+
row: "root",
|
|
60369
|
+
keys: [
|
|
60370
|
+
"maxDecodeFps",
|
|
60371
|
+
"initialReconnectDelayMs",
|
|
60372
|
+
"maxReconnectDelayMs"
|
|
60373
|
+
],
|
|
60374
|
+
perNodeKeys: [],
|
|
60375
|
+
reason: "three form knobs deleted 2026-08-28 (D272): nothing capped decode fps, and the reconnect ladder has always run on the INITIAL/MAX_RECONNECT_DELAY_MS constants"
|
|
60376
|
+
},
|
|
60377
|
+
{
|
|
60378
|
+
namespace: "embedding-encoder",
|
|
60379
|
+
collection: "addon-settings",
|
|
60380
|
+
row: "root",
|
|
60381
|
+
keys: ["runtime", "backend"],
|
|
60382
|
+
perNodeKeys: [],
|
|
60383
|
+
reason: "two selects deleted 2026-08-28 (D272); their only reference was a withTags log field, and the CUDA/CoreML options named acceleration that has never existed \u2014 embedding inference is always ONNX in the embedded Python"
|
|
60384
|
+
},
|
|
60385
|
+
{
|
|
60386
|
+
namespace: "audio-analyzer",
|
|
60387
|
+
collection: "addon-settings",
|
|
60388
|
+
row: "root",
|
|
60389
|
+
keys: ["selectedAudioModel", "probedBestAudioBackend"],
|
|
60390
|
+
perNodeKeys: [],
|
|
60391
|
+
reason: "`selectedAudioModel` deleted 2026-08-28 (D272) \u2014 createAudioPipeline takes a backend and no model id, so it never reached inference; the BARE `probedBestAudioBackend` is pre-perNode residue that projectStore already drops (no bare fallback), so no node can ever read it"
|
|
60392
|
+
},
|
|
60393
|
+
{
|
|
60394
|
+
namespace: "decoder-nodeav",
|
|
60395
|
+
collection: "addon-settings",
|
|
60396
|
+
row: "root",
|
|
60397
|
+
keys: ["probedBestHwaccel"],
|
|
60398
|
+
perNodeKeys: [],
|
|
60399
|
+
reason: "bare pre-perNode residue \u2014 the live probe result is `probedBestHwaccel@<nodeId>` and `projectStore` deliberately drops the bare key, so nothing can read it"
|
|
60400
|
+
},
|
|
60401
|
+
{
|
|
60402
|
+
namespace: "pipeline-analytics",
|
|
60403
|
+
collection: "addon-settings",
|
|
60404
|
+
row: "root",
|
|
60405
|
+
keys: ["mediaAttachPolicy"],
|
|
60406
|
+
perNodeKeys: [],
|
|
60407
|
+
reason: "deleted 2026-08-28 (D272) \u2014 absent from MediaSettingsSchema, so the value was never even resolved, let alone read"
|
|
60408
|
+
}
|
|
60409
|
+
];
|
|
60230
60410
|
var RETIRED_SETTINGS_ROWS = [
|
|
60231
60411
|
{
|
|
60232
60412
|
collection: "addon-settings",
|
|
@@ -62363,8 +62543,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
62363
62543
|
[Symbol.toStringTag]: { value: "Module" }
|
|
62364
62544
|
});
|
|
62365
62545
|
require_chunk_Cek0wNdY();
|
|
62366
|
-
var require_dist10 =
|
|
62367
|
-
var require_retired_settings_keys =
|
|
62546
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
62547
|
+
var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
|
|
62368
62548
|
var node_crypto = __require("crypto");
|
|
62369
62549
|
var _camstack_types_node = require_node();
|
|
62370
62550
|
var JOB_HISTORY = 20;
|
|
@@ -67113,7 +67293,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
67113
67293
|
[Symbol.toStringTag]: { value: "Module" }
|
|
67114
67294
|
});
|
|
67115
67295
|
require_chunk_Cek0wNdY();
|
|
67116
|
-
var require_dist10 =
|
|
67296
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
67117
67297
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
67118
67298
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
67119
67299
|
var HubForwarderDestination = class {
|
|
@@ -67250,7 +67430,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
67250
67430
|
"use strict";
|
|
67251
67431
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
67252
67432
|
require_chunk_Cek0wNdY();
|
|
67253
|
-
var require_dist10 =
|
|
67433
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
67254
67434
|
var NO_DEVICES = "liveness:no-devices";
|
|
67255
67435
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
67256
67436
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -67440,7 +67620,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
67440
67620
|
[Symbol.toStringTag]: { value: "Module" }
|
|
67441
67621
|
});
|
|
67442
67622
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
67443
|
-
var require_dist10 =
|
|
67623
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
67444
67624
|
var node_crypto = __require("crypto");
|
|
67445
67625
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
67446
67626
|
var crypto$1 = __require("crypto");
|
|
@@ -71954,6 +72134,99 @@ var require_local_auth_addon = __commonJS({
|
|
|
71954
72134
|
};
|
|
71955
72135
|
}));
|
|
71956
72136
|
var import_jsonwebtoken = /* @__PURE__ */ require_chunk.__toESM(require_jsonwebtoken());
|
|
72137
|
+
var DURATION_PATTERN = /^(\d+(?:\.\d+)?)\s*(ms|milliseconds?|msecs?|s|secs?|seconds?|m|mins?|minutes?|h|hrs?|hours?|d|days?|w|weeks?|y|yrs?|years?)$/i;
|
|
72138
|
+
var UNIT_MS = {
|
|
72139
|
+
ms: 1,
|
|
72140
|
+
msec: 1,
|
|
72141
|
+
msecs: 1,
|
|
72142
|
+
millisecond: 1,
|
|
72143
|
+
milliseconds: 1,
|
|
72144
|
+
s: 1e3,
|
|
72145
|
+
sec: 1e3,
|
|
72146
|
+
secs: 1e3,
|
|
72147
|
+
second: 1e3,
|
|
72148
|
+
seconds: 1e3,
|
|
72149
|
+
m: 6e4,
|
|
72150
|
+
min: 6e4,
|
|
72151
|
+
mins: 6e4,
|
|
72152
|
+
minute: 6e4,
|
|
72153
|
+
minutes: 6e4,
|
|
72154
|
+
h: 36e5,
|
|
72155
|
+
hr: 36e5,
|
|
72156
|
+
hrs: 36e5,
|
|
72157
|
+
hour: 36e5,
|
|
72158
|
+
hours: 36e5,
|
|
72159
|
+
d: 864e5,
|
|
72160
|
+
day: 864e5,
|
|
72161
|
+
days: 864e5,
|
|
72162
|
+
w: 6048e5,
|
|
72163
|
+
week: 6048e5,
|
|
72164
|
+
weeks: 6048e5,
|
|
72165
|
+
y: 315576e5,
|
|
72166
|
+
yr: 315576e5,
|
|
72167
|
+
yrs: 315576e5,
|
|
72168
|
+
year: 315576e5,
|
|
72169
|
+
years: 315576e5
|
|
72170
|
+
};
|
|
72171
|
+
var MIN_EXPIRY_MS = 6e4;
|
|
72172
|
+
var MAX_EXPIRY_MS = 365 * 864e5;
|
|
72173
|
+
function durationMs(candidate) {
|
|
72174
|
+
const match = DURATION_PATTERN.exec(candidate);
|
|
72175
|
+
if (match === null) return null;
|
|
72176
|
+
const amount = Number(match[1]);
|
|
72177
|
+
const unitMs = UNIT_MS[match[2].toLowerCase()];
|
|
72178
|
+
if (!Number.isFinite(amount) || unitMs === void 0) return null;
|
|
72179
|
+
return amount * unitMs;
|
|
72180
|
+
}
|
|
72181
|
+
var DEFAULT_SECONDS = (() => {
|
|
72182
|
+
const ms = durationMs("30d");
|
|
72183
|
+
if (ms === null) throw new Error(`DEFAULT_TOKEN_EXPIRY is not a duration: 30d`);
|
|
72184
|
+
return ms / 1e3;
|
|
72185
|
+
})();
|
|
72186
|
+
function refuse(reason) {
|
|
72187
|
+
return {
|
|
72188
|
+
ok: false,
|
|
72189
|
+
reason,
|
|
72190
|
+
seconds: DEFAULT_SECONDS,
|
|
72191
|
+
value: "30d"
|
|
72192
|
+
};
|
|
72193
|
+
}
|
|
72194
|
+
function parseTokenExpiry(configured) {
|
|
72195
|
+
if (configured === void 0 || configured === null) return {
|
|
72196
|
+
ok: true,
|
|
72197
|
+
seconds: DEFAULT_SECONDS,
|
|
72198
|
+
value: "30d"
|
|
72199
|
+
};
|
|
72200
|
+
if (typeof configured !== "string") return refuse("not-a-string");
|
|
72201
|
+
const trimmed = configured.trim();
|
|
72202
|
+
if (trimmed === "") return {
|
|
72203
|
+
ok: true,
|
|
72204
|
+
seconds: DEFAULT_SECONDS,
|
|
72205
|
+
value: "30d"
|
|
72206
|
+
};
|
|
72207
|
+
const totalMs = durationMs(trimmed);
|
|
72208
|
+
if (totalMs === null) return refuse("malformed");
|
|
72209
|
+
if (totalMs < MIN_EXPIRY_MS) return refuse("too-short");
|
|
72210
|
+
if (totalMs > MAX_EXPIRY_MS) return refuse("too-long");
|
|
72211
|
+
return {
|
|
72212
|
+
ok: true,
|
|
72213
|
+
seconds: totalMs / 1e3,
|
|
72214
|
+
value: trimmed
|
|
72215
|
+
};
|
|
72216
|
+
}
|
|
72217
|
+
var REJECTION_DETAIL = {
|
|
72218
|
+
"not-a-string": "value is not a string",
|
|
72219
|
+
malformed: "not a duration string (expected e.g. 24h, 7d, 30d \u2014 a bare number is NOT seconds)",
|
|
72220
|
+
"too-short": `shorter than the ${MIN_EXPIRY_MS / 1e3}s minimum`,
|
|
72221
|
+
"too-long": `longer than the ${MAX_EXPIRY_MS / 864e5}d maximum`
|
|
72222
|
+
};
|
|
72223
|
+
function logTokenExpiryRejection(configured, rejection, logger) {
|
|
72224
|
+
logger.warn(`auth.tokenExpiry REJECTED \u2014 ${REJECTION_DETAIL[rejection.reason]}; signing with the default 30d instead`, { meta: {
|
|
72225
|
+
configured,
|
|
72226
|
+
reason: rejection.reason,
|
|
72227
|
+
applied: rejection.value
|
|
72228
|
+
} });
|
|
72229
|
+
}
|
|
71957
72230
|
var noopLogger = {
|
|
71958
72231
|
debug() {
|
|
71959
72232
|
},
|
|
@@ -71974,6 +72247,16 @@ var require_local_auth_addon = __commonJS({
|
|
|
71974
72247
|
config;
|
|
71975
72248
|
jwtSecret;
|
|
71976
72249
|
logger;
|
|
72250
|
+
/**
|
|
72251
|
+
* Offending `auth.tokenExpiry` values already reported by this instance.
|
|
72252
|
+
*
|
|
72253
|
+
* `signToken` re-reads the setting on EVERY mint so an operator's change
|
|
72254
|
+
* takes effect without a restart — which also means a bad value would log
|
|
72255
|
+
* once per login and once per silent refresh from every viewer. The refusal
|
|
72256
|
+
* must be visible, not repeated: the first mint after a bad save logs, the
|
|
72257
|
+
* rest resolve silently to the same default until the value changes.
|
|
72258
|
+
*/
|
|
72259
|
+
reportedInvalidExpiries = /* @__PURE__ */ new Set();
|
|
71977
72260
|
constructor(config, logger = noopLogger) {
|
|
71978
72261
|
this.config = config;
|
|
71979
72262
|
this.logger = logger;
|
|
@@ -71988,8 +72271,15 @@ var require_local_auth_addon = __commonJS({
|
|
|
71988
72271
|
}
|
|
71989
72272
|
signToken(payload) {
|
|
71990
72273
|
const configured = this.config.get("auth.tokenExpiry");
|
|
71991
|
-
const
|
|
71992
|
-
|
|
72274
|
+
const parsed = parseTokenExpiry(configured);
|
|
72275
|
+
if (!parsed.ok) {
|
|
72276
|
+
const seen = typeof configured === "string" ? configured : JSON.stringify(configured);
|
|
72277
|
+
if (!this.reportedInvalidExpiries.has(seen)) {
|
|
72278
|
+
this.reportedInvalidExpiries.add(seen);
|
|
72279
|
+
logTokenExpiryRejection(configured, parsed, this.logger);
|
|
72280
|
+
}
|
|
72281
|
+
}
|
|
72282
|
+
return import_jsonwebtoken.sign({ ...payload }, this.jwtSecret, { expiresIn: parsed.seconds });
|
|
71993
72283
|
}
|
|
71994
72284
|
verifyToken(token2) {
|
|
71995
72285
|
return import_jsonwebtoken.verify(token2, this.jwtSecret);
|
|
@@ -74276,6 +74566,30 @@ var require_local_auth_addon = __commonJS({
|
|
|
74276
74566
|
return parseRow(results[0].data);
|
|
74277
74567
|
}
|
|
74278
74568
|
};
|
|
74569
|
+
function createAuthConfigReader(resolved, writeAuthSection) {
|
|
74570
|
+
return {
|
|
74571
|
+
get(path) {
|
|
74572
|
+
switch (path) {
|
|
74573
|
+
case "auth.jwtSecret":
|
|
74574
|
+
return narrow(resolved.jwtSecret);
|
|
74575
|
+
case "auth.adminUsername":
|
|
74576
|
+
return narrow(resolved.adminUsername);
|
|
74577
|
+
case "auth.adminPassword":
|
|
74578
|
+
return narrow(resolved.adminPassword);
|
|
74579
|
+
case "auth.tokenExpiry":
|
|
74580
|
+
return narrow(resolved.tokenExpiry);
|
|
74581
|
+
default:
|
|
74582
|
+
return;
|
|
74583
|
+
}
|
|
74584
|
+
},
|
|
74585
|
+
update(_section, data) {
|
|
74586
|
+
if (typeof data["jwtSecret"] === "string") writeAuthSection({ jwtSecret: data["jwtSecret"] });
|
|
74587
|
+
}
|
|
74588
|
+
};
|
|
74589
|
+
}
|
|
74590
|
+
function narrow(value) {
|
|
74591
|
+
return value;
|
|
74592
|
+
}
|
|
74279
74593
|
var USERS_COLLECTION = "users";
|
|
74280
74594
|
var API_KEYS_COLLECTION = "api_keys";
|
|
74281
74595
|
var SCOPED_TOKENS_COLLECTION = "scoped_tokens";
|
|
@@ -74806,19 +75120,14 @@ var require_local_auth_addon = __commonJS({
|
|
|
74806
75120
|
}
|
|
74807
75121
|
async onInitialize() {
|
|
74808
75122
|
const authSection = await this.ctx.settings?.getSection("auth") ?? {};
|
|
74809
|
-
const
|
|
74810
|
-
|
|
74811
|
-
|
|
74812
|
-
|
|
74813
|
-
|
|
74814
|
-
|
|
74815
|
-
|
|
74816
|
-
|
|
74817
|
-
},
|
|
74818
|
-
update: (_section, data) => {
|
|
74819
|
-
if (typeof data["jwtSecret"] === "string") this.ctx.settings?.setSection("auth", { jwtSecret: data["jwtSecret"] });
|
|
74820
|
-
}
|
|
74821
|
-
};
|
|
75123
|
+
const reader = createAuthConfigReader({
|
|
75124
|
+
jwtSecret: typeof authSection["jwtSecret"] === "string" ? authSection["jwtSecret"] : this.config.jwtSecret ?? "",
|
|
75125
|
+
adminUsername: typeof authSection["adminUsername"] === "string" && authSection["adminUsername"] ? authSection["adminUsername"] : this.config.adminUsername ?? "",
|
|
75126
|
+
adminPassword: typeof authSection["adminPassword"] === "string" && authSection["adminPassword"] ? authSection["adminPassword"] : this.config.adminPassword ?? "",
|
|
75127
|
+
tokenExpiry: typeof authSection["tokenExpiry"] === "string" && authSection["tokenExpiry"] ? authSection["tokenExpiry"] : void 0
|
|
75128
|
+
}, (patch) => {
|
|
75129
|
+
this.ctx.settings?.setSection("auth", patch);
|
|
75130
|
+
});
|
|
74822
75131
|
this.authManager = new AuthManager(reader, this.ctx.logger);
|
|
74823
75132
|
const store = this.ctx.api?.settingsStore;
|
|
74824
75133
|
if (store) {
|
|
@@ -75124,7 +75433,7 @@ var require_loki_logging = __commonJS({
|
|
|
75124
75433
|
[Symbol.toStringTag]: { value: "Module" }
|
|
75125
75434
|
});
|
|
75126
75435
|
require_chunk_Cek0wNdY();
|
|
75127
|
-
var require_dist10 =
|
|
75436
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
75128
75437
|
function sanitizeLabelName(raw) {
|
|
75129
75438
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
75130
75439
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -75689,7 +75998,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
75689
75998
|
[Symbol.toStringTag]: { value: "Module" }
|
|
75690
75999
|
});
|
|
75691
76000
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
75692
|
-
var require_dist10 =
|
|
76001
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
75693
76002
|
var node_fs_promises = __require("fs/promises");
|
|
75694
76003
|
var node_child_process = __require("child_process");
|
|
75695
76004
|
var node_util = __require("util");
|
|
@@ -77646,7 +77955,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
77646
77955
|
[Symbol.toStringTag]: { value: "Module" }
|
|
77647
77956
|
});
|
|
77648
77957
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
77649
|
-
var require_dist10 =
|
|
77958
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
77650
77959
|
var node_crypto = __require("crypto");
|
|
77651
77960
|
var node_fs_promises = __require("fs/promises");
|
|
77652
77961
|
var node_path = __require("path");
|
|
@@ -78762,8 +79071,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
78762
79071
|
[Symbol.toStringTag]: { value: "Module" }
|
|
78763
79072
|
});
|
|
78764
79073
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
78765
|
-
var require_dist10 =
|
|
78766
|
-
var require_retired_settings_keys =
|
|
79074
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
79075
|
+
var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
|
|
78767
79076
|
var node_crypto = __require("crypto");
|
|
78768
79077
|
var node_fs = __require("fs");
|
|
78769
79078
|
var node_module = __require("module");
|
|
@@ -81042,7 +81351,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
81042
81351
|
[Symbol.toStringTag]: { value: "Module" }
|
|
81043
81352
|
});
|
|
81044
81353
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
81045
|
-
var require_dist10 =
|
|
81354
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
81046
81355
|
var node_crypto = __require("crypto");
|
|
81047
81356
|
var node_fs_promises = __require("fs/promises");
|
|
81048
81357
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -82923,7 +83232,7 @@ var require_system_config_addon = __commonJS({
|
|
|
82923
83232
|
[Symbol.toStringTag]: { value: "Module" }
|
|
82924
83233
|
});
|
|
82925
83234
|
require_chunk_Cek0wNdY();
|
|
82926
|
-
var require_dist10 =
|
|
83235
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
82927
83236
|
var SECTION_TITLES = {
|
|
82928
83237
|
server: "Server",
|
|
82929
83238
|
auth: "Authentication"
|
|
@@ -82988,7 +83297,7 @@ var require_system_config_addon = __commonJS({
|
|
|
82988
83297
|
type: "text",
|
|
82989
83298
|
key: "tokenExpiry",
|
|
82990
83299
|
label: "Token Expiry",
|
|
82991
|
-
description: "
|
|
83300
|
+
description: "Lifetime of a session token, as a duration string (e.g. 24h, 7d, 30d). A bare number is rejected \u2014 it would be read as milliseconds. Applies to tokens issued from the next login or silent refresh; tokens already handed out keep the lifetime they were signed with.",
|
|
82992
83301
|
placeholder: "30d",
|
|
82993
83302
|
default: "30d"
|
|
82994
83303
|
}]
|
|
@@ -100984,7 +101293,7 @@ var require_winston_logging = __commonJS({
|
|
|
100984
101293
|
[Symbol.toStringTag]: { value: "Module" }
|
|
100985
101294
|
});
|
|
100986
101295
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
100987
|
-
var require_dist10 =
|
|
101296
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
100988
101297
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
100989
101298
|
var node_path = __require("path");
|
|
100990
101299
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -102927,9 +103236,9 @@ var require_event_category_BaEgqJNv = __commonJS({
|
|
|
102927
103236
|
}
|
|
102928
103237
|
});
|
|
102929
103238
|
|
|
102930
|
-
// ../types/dist/sleep-
|
|
102931
|
-
var
|
|
102932
|
-
"../types/dist/sleep-
|
|
103239
|
+
// ../types/dist/sleep-DUxF5DdC.js
|
|
103240
|
+
var require_sleep_DUxF5DdC = __commonJS({
|
|
103241
|
+
"../types/dist/sleep-DUxF5DdC.js"(exports) {
|
|
102933
103242
|
"use strict";
|
|
102934
103243
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
102935
103244
|
var zod = require_zod();
|
|
@@ -103418,6 +103727,40 @@ var require_sleep_9d8tJRbO = __commonJS({
|
|
|
103418
103727
|
deviceSettingsSchema() {
|
|
103419
103728
|
return null;
|
|
103420
103729
|
}
|
|
103730
|
+
/**
|
|
103731
|
+
* INTEGRATION-LEVEL SETTINGS — declare which of this addon's global sections
|
|
103732
|
+
* ARE the configuration of its integration.
|
|
103733
|
+
*
|
|
103734
|
+
* Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
|
|
103735
|
+
* operator should find on the addon's integration page (System →
|
|
103736
|
+
* Integrations → <name>) rather than only in the cluster-wide list of every
|
|
103737
|
+
* addon. Empty (the default) means the addon has no integration-level
|
|
103738
|
+
* settings and no such surface is offered — this is opt-in, because whether
|
|
103739
|
+
* an addon's configuration IS its integration's configuration depends on the
|
|
103740
|
+
* nature of the integration.
|
|
103741
|
+
*
|
|
103742
|
+
* WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
|
|
103743
|
+
* the ONE global schema, in the ONE addon store, written by the ONE
|
|
103744
|
+
* `updateGlobalSettings` path. There is deliberately no
|
|
103745
|
+
* `updateIntegrationSettings`: a second write path is how a surface acquires
|
|
103746
|
+
* a second store key, and this repo has shipped that twice (`btmPath@hub`,
|
|
103747
|
+
* D266). Selecting sections cannot introduce a key that selecting cannot.
|
|
103748
|
+
*
|
|
103749
|
+
* WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
|
|
103750
|
+
* `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
|
|
103751
|
+
* removed with the reason recorded at
|
|
103752
|
+
* `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
|
|
103753
|
+
* determined by WHICH schema it lives in, not by a field-level marker."* A
|
|
103754
|
+
* marker sprinkled across sections also has to borrow a field that already
|
|
103755
|
+
* means something else; borrowing `section.tab` put the literal word
|
|
103756
|
+
* "integration" into an operator-facing tab bar, because `tab` means "how to
|
|
103757
|
+
* GROUP this visually" and cannot also mean "where this lives" (D269
|
|
103758
|
+
* supersedes D268). One declaration, in one place, next to the schema whose
|
|
103759
|
+
* ids it names.
|
|
103760
|
+
*/
|
|
103761
|
+
integrationSettingSections() {
|
|
103762
|
+
return [];
|
|
103763
|
+
}
|
|
103421
103764
|
async getGlobalSettings(overlay, cap, nodeId) {
|
|
103422
103765
|
const schema = this.globalSettingsSchema(cap);
|
|
103423
103766
|
if (!schema) return { sections: [] };
|
|
@@ -103428,6 +103771,55 @@ var require_sleep_9d8tJRbO = __commonJS({
|
|
|
103428
103771
|
} : projected);
|
|
103429
103772
|
}
|
|
103430
103773
|
/**
|
|
103774
|
+
* The integration-level view of this addon's settings: exactly the sections
|
|
103775
|
+
* named by {@link integrationSettingSections}, hydrated from the SAME store
|
|
103776
|
+
* `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
|
|
103777
|
+
*
|
|
103778
|
+
* Returns `null` when the addon declared nothing — an addon that opts out has
|
|
103779
|
+
* no integration settings surface at all, rather than an empty one that reads
|
|
103780
|
+
* as a failed load.
|
|
103781
|
+
*
|
|
103782
|
+
* Three properties hold BY CONSTRUCTION, which is why they are here in core
|
|
103783
|
+
* and not in whichever UI happens to render this:
|
|
103784
|
+
*
|
|
103785
|
+
* 1. **One key.** The payload is a SUBSET of the global schema, so a field
|
|
103786
|
+
* shown here is the same field, with the same bare key, that the addon's
|
|
103787
|
+
* own page shows. There is no integration-specific writer — callers save
|
|
103788
|
+
* through `updateGlobalSettings` — so a second store key is unreachable,
|
|
103789
|
+
* not merely discouraged.
|
|
103790
|
+
* 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
|
|
103791
|
+
* is `<key>@<nodeId>` and an integration is not a node; whichever node
|
|
103792
|
+
* such a field silently picked would be a wrong answer for the operator
|
|
103793
|
+
* who opened the page (D266).
|
|
103794
|
+
* 3. **No silent typo.** A declared id that names no section throws. The
|
|
103795
|
+
* alternative — skip it — turns a rename into a surface that quietly
|
|
103796
|
+
* empties, which looks exactly like an addon with nothing to configure.
|
|
103797
|
+
*/
|
|
103798
|
+
async getIntegrationSettings(nodeId) {
|
|
103799
|
+
const declared = this.integrationSettingSections();
|
|
103800
|
+
if (declared.length === 0) return null;
|
|
103801
|
+
const schema = this.globalSettingsSchema();
|
|
103802
|
+
if (!schema) throw new Error(`${this.constructor.name}: integrationSettingSections() names [${declared.join(", ")}] but globalSettingsSchema() returns null.`);
|
|
103803
|
+
const byId = new Map(schema.sections.map((section) => [section.id, section]));
|
|
103804
|
+
const sections = [];
|
|
103805
|
+
for (const id of declared) {
|
|
103806
|
+
const section = byId.get(id);
|
|
103807
|
+
if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
|
|
103808
|
+
const fields = dropPerNodeFields(section.fields);
|
|
103809
|
+
if (fields.length === 0) continue;
|
|
103810
|
+
sections.push({
|
|
103811
|
+
...section,
|
|
103812
|
+
fields
|
|
103813
|
+
});
|
|
103814
|
+
}
|
|
103815
|
+
if (sections.length === 0) return null;
|
|
103816
|
+
const projected = await this.resolveGlobalStore(nodeId);
|
|
103817
|
+
return hydrateSchema({
|
|
103818
|
+
...schema,
|
|
103819
|
+
sections
|
|
103820
|
+
}, projected);
|
|
103821
|
+
}
|
|
103822
|
+
/**
|
|
103431
103823
|
* The raw addon store PROJECTED onto the target node's bare per-node keys:
|
|
103432
103824
|
* every `perNode: true` field carries THAT node's scoped value on its bare
|
|
103433
103825
|
* key (absent scoped key ⇒ key absent, so the schema `default` wins — no
|
|
@@ -103727,6 +104119,33 @@ var require_sleep_9d8tJRbO = __commonJS({
|
|
|
103727
104119
|
return {};
|
|
103728
104120
|
}
|
|
103729
104121
|
};
|
|
104122
|
+
function dropPerNodeFields(fields) {
|
|
104123
|
+
const kept = [];
|
|
104124
|
+
for (const field of fields) {
|
|
104125
|
+
if (field.type === "group") {
|
|
104126
|
+
const inner = dropPerNodeFields(field.fields);
|
|
104127
|
+
if (inner.length > 0) kept.push({
|
|
104128
|
+
...field,
|
|
104129
|
+
fields: inner
|
|
104130
|
+
});
|
|
104131
|
+
continue;
|
|
104132
|
+
}
|
|
104133
|
+
if (field.type === "sub-tabs") {
|
|
104134
|
+
const tabs = field.tabs.map((tab) => ({
|
|
104135
|
+
...tab,
|
|
104136
|
+
fields: dropPerNodeFields(tab.fields)
|
|
104137
|
+
})).filter((tab) => tab.fields.length > 0);
|
|
104138
|
+
if (tabs.length > 0) kept.push({
|
|
104139
|
+
...field,
|
|
104140
|
+
tabs
|
|
104141
|
+
});
|
|
104142
|
+
continue;
|
|
104143
|
+
}
|
|
104144
|
+
if ("perNode" in field && field.perNode === true) continue;
|
|
104145
|
+
kept.push(field);
|
|
104146
|
+
}
|
|
104147
|
+
return kept;
|
|
104148
|
+
}
|
|
103730
104149
|
function collectPerNodeFieldKeys(fields) {
|
|
103731
104150
|
const collected = [];
|
|
103732
104151
|
for (const field of fields) {
|
|
@@ -106483,7 +106902,7 @@ var require_addon = __commonJS({
|
|
|
106483
106902
|
"use strict";
|
|
106484
106903
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
106485
106904
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
106486
|
-
var require_sleep =
|
|
106905
|
+
var require_sleep = require_sleep_DUxF5DdC();
|
|
106487
106906
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
106488
106907
|
var CAP_INPUT_DEFAULTS = Object.freeze({
|
|
106489
106908
|
"addons": { "getLogs": { "limit": 100 } },
|
|
@@ -113361,12 +113780,12 @@ var require_dist2 = __commonJS({
|
|
|
113361
113780
|
}
|
|
113362
113781
|
});
|
|
113363
113782
|
|
|
113364
|
-
// ../system/dist/manifest-python-deps-
|
|
113365
|
-
var
|
|
113366
|
-
"../system/dist/manifest-python-deps-
|
|
113783
|
+
// ../system/dist/manifest-python-deps-CivtrAha.js
|
|
113784
|
+
var require_manifest_python_deps_CivtrAha = __commonJS({
|
|
113785
|
+
"../system/dist/manifest-python-deps-CivtrAha.js"(exports) {
|
|
113367
113786
|
"use strict";
|
|
113368
113787
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
113369
|
-
|
|
113788
|
+
require_dist_DdEXjTDo();
|
|
113370
113789
|
var node_crypto = __require("crypto");
|
|
113371
113790
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
113372
113791
|
var _camstack_types_node = require_node();
|
|
@@ -124481,7 +124900,7 @@ var require_dist3 = __commonJS({
|
|
|
124481
124900
|
"use strict";
|
|
124482
124901
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
124483
124902
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
124484
|
-
var require_dist10 =
|
|
124903
|
+
var require_dist10 = require_dist_DdEXjTDo();
|
|
124485
124904
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
124486
124905
|
require_alerts();
|
|
124487
124906
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -124507,7 +124926,7 @@ var require_dist3 = __commonJS({
|
|
|
124507
124926
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
124508
124927
|
var require_file_data_plane = require_file_data_plane_DO8KbxCe();
|
|
124509
124928
|
var require_tls$1 = require_tls_u8QCJCFE();
|
|
124510
|
-
var require_manifest_python_deps =
|
|
124929
|
+
var require_manifest_python_deps = require_manifest_python_deps_CivtrAha();
|
|
124511
124930
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
124512
124931
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
124513
124932
|
var zod = require_zod();
|
|
@@ -205223,7 +205642,7 @@ var require_dist4 = __commonJS({
|
|
|
205223
205642
|
"use strict";
|
|
205224
205643
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
205225
205644
|
var require_event_category = require_event_category_BaEgqJNv();
|
|
205226
|
-
var require_sleep =
|
|
205645
|
+
var require_sleep = require_sleep_DUxF5DdC();
|
|
205227
205646
|
var require_canonical_hash = require_canonical_hash_DNV8S5ET();
|
|
205228
205647
|
var require_enums2 = require_enums();
|
|
205229
205648
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
@@ -208876,6 +209295,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
208876
209295
|
kind: "mutation",
|
|
208877
209296
|
auth: "admin"
|
|
208878
209297
|
}),
|
|
209298
|
+
getIntegrationSettings: require_sleep.method(zod.z.object({
|
|
209299
|
+
addonId: zod.z.string(),
|
|
209300
|
+
nodeId: zod.z.string().optional()
|
|
209301
|
+
}), SettingsSchemaWithValuesSchema.nullable()),
|
|
208879
209302
|
getDeviceSettings: require_sleep.method(zod.z.object({
|
|
208880
209303
|
addonId: zod.z.string(),
|
|
208881
209304
|
deviceId: zod.z.number(),
|
|
@@ -209155,8 +209578,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
209155
209578
|
];
|
|
209156
209579
|
var DEFAULT_AUDIO_ANALYZER_CONFIG = {
|
|
209157
209580
|
audioBackend: "auto",
|
|
209158
|
-
probedBestAudioBackend: ""
|
|
209159
|
-
selectedAudioModel: ""
|
|
209581
|
+
probedBestAudioBackend: ""
|
|
209160
209582
|
};
|
|
209161
209583
|
var audioAnalyzerCapability = {
|
|
209162
209584
|
name: "audio-analyzer",
|
|
@@ -231423,6 +231845,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
231423
231845
|
}
|
|
231424
231846
|
var HF_REPO = "camstack/camstack-models";
|
|
231425
231847
|
var HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`;
|
|
231848
|
+
var DEFAULT_TOKEN_EXPIRY = "30d";
|
|
231426
231849
|
var RUNTIME_DEFAULTS = {
|
|
231427
231850
|
"features.streaming": true,
|
|
231428
231851
|
"features.notifications": true,
|
|
@@ -231451,7 +231874,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
231451
231874
|
"ffmpeg.binaryPath": "ffmpeg",
|
|
231452
231875
|
"ffmpeg.hwAccel": "auto",
|
|
231453
231876
|
"ffmpeg.threadCount": 0,
|
|
231454
|
-
"auth.tokenExpiry": "
|
|
231877
|
+
"auth.tokenExpiry": "30d"
|
|
231455
231878
|
};
|
|
231456
231879
|
var AccessoryKind = {
|
|
231457
231880
|
Siren: require_sleep.DeviceRole.Siren,
|
|
@@ -235050,6 +235473,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
235050
235473
|
addonId: null,
|
|
235051
235474
|
access: "view"
|
|
235052
235475
|
},
|
|
235476
|
+
"addonSettings.getIntegrationSettings": {
|
|
235477
|
+
capName: "addon-settings",
|
|
235478
|
+
capScope: "system",
|
|
235479
|
+
addonId: null,
|
|
235480
|
+
access: "view"
|
|
235481
|
+
},
|
|
235053
235482
|
"addonSettings.updateDeviceSettings": {
|
|
235054
235483
|
capName: "addon-settings",
|
|
235055
235484
|
capScope: "system",
|
|
@@ -243252,7 +243681,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
243252
243681
|
},
|
|
243253
243682
|
addonSettings: {
|
|
243254
243683
|
getGlobalSettings: (input) => dispatch("addonSettings", "getGlobalSettings", "query", input),
|
|
243255
|
-
updateGlobalSettings: (input) => dispatch("addonSettings", "updateGlobalSettings", "mutation", input)
|
|
243684
|
+
updateGlobalSettings: (input) => dispatch("addonSettings", "updateGlobalSettings", "mutation", input),
|
|
243685
|
+
getIntegrationSettings: (input) => dispatch("addonSettings", "getIntegrationSettings", "query", input)
|
|
243256
243686
|
},
|
|
243257
243687
|
addonWidgets: { listWidgets: (input) => dispatch("addonWidgets", "listWidgets", "query", input) },
|
|
243258
243688
|
alerts: {
|
|
@@ -246697,6 +247127,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
246697
247127
|
exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
|
|
246698
247128
|
exports.DEFAULT_RUNTIME_STATE_DURABILITY = require_sleep.DEFAULT_RUNTIME_STATE_DURABILITY;
|
|
246699
247129
|
exports.DEFAULT_TIMELAPSE_PREVIEW_TEXT = DEFAULT_TIMELAPSE_PREVIEW_TEXT;
|
|
247130
|
+
exports.DEFAULT_TOKEN_EXPIRY = DEFAULT_TOKEN_EXPIRY;
|
|
246700
247131
|
exports.DETAIL_CROP_PADDING_FIELD = DETAIL_CROP_PADDING_FIELD;
|
|
246701
247132
|
exports.DETAIL_CROP_PADDING_KEY = DETAIL_CROP_PADDING_KEY;
|
|
246702
247133
|
exports.DETAIL_CROP_SECTION_ID = DETAIL_CROP_SECTION_ID;
|
|
@@ -412320,6 +412751,16 @@ var require_addon_settings_provider = __commonJS({
|
|
|
412320
412751
|
}
|
|
412321
412752
|
return forkedUpdate(input.addonId, "updateGlobalSettings", { patch: input.patch, ...input.nodeId ? { nodeId: input.nodeId } : {} }, input.nodeId);
|
|
412322
412753
|
},
|
|
412754
|
+
async getIntegrationSettings(input) {
|
|
412755
|
+
if (gateway.isInProcess(input.addonId, input.nodeId)) {
|
|
412756
|
+
const addon = getAddon(input.addonId);
|
|
412757
|
+
if (!addon || typeof addon.getIntegrationSettings !== "function")
|
|
412758
|
+
return null;
|
|
412759
|
+
const result = await addon.getIntegrationSettings(input.nodeId);
|
|
412760
|
+
return result ? reshapeForOutput(result) : null;
|
|
412761
|
+
}
|
|
412762
|
+
return forkedGet(input.addonId, "getIntegrationSettings", { ...input.nodeId ? { nodeId: input.nodeId } : {} }, input.nodeId);
|
|
412763
|
+
},
|
|
412323
412764
|
async getDeviceSettings(input) {
|
|
412324
412765
|
if (gateway.isInProcess(input.addonId, input.nodeId)) {
|
|
412325
412766
|
const addon = getAddon(input.addonId);
|