camstack 1.2.67 → 1.2.68

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-ot6dTHCA.mjs
14525
+ // ../types/dist/sleep-BS40IUZZ.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -26399,6 +26399,25 @@ var EventStoreFootprintSchema = external_exports.object({
26399
26399
  totalBytes: external_exports.number().int(),
26400
26400
  devices: external_exports.array(EventStoreDeviceFootprintSchema).readonly()
26401
26401
  });
26402
+ var EventMediaKindFootprintSchema = external_exports.object({
26403
+ kind: MediaFileKindEnum,
26404
+ /** Media rows of this kind. */
26405
+ rows: external_exports.number().int(),
26406
+ /** Bytes on disk held by those rows. */
26407
+ bytes: external_exports.number().int()
26408
+ });
26409
+ var EventMediaKindBreakdownSchema = external_exports.object({
26410
+ /** Every media row in scope, from one unfiltered aggregate. */
26411
+ totalRows: external_exports.number().int(),
26412
+ /** Every media byte in scope, from that same aggregate. */
26413
+ totalBytes: external_exports.number().int(),
26414
+ /** Per-kind footprint, ordered by bytes descending. */
26415
+ kinds: external_exports.array(EventMediaKindFootprintSchema).readonly(),
26416
+ /** `totalRows` minus the summed `kinds` rows — see the schema note. */
26417
+ unaccountedRows: external_exports.number().int(),
26418
+ /** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
26419
+ unaccountedBytes: external_exports.number().int()
26420
+ });
26402
26421
  var EventPruneCountsSchema = external_exports.object({
26403
26422
  motion: external_exports.number().int(),
26404
26423
  object: external_exports.number().int(),
@@ -26754,6 +26773,22 @@ var pipelineAnalyticsCapability = {
26754
26773
  auth: "admin"
26755
26774
  }),
26756
26775
  /**
26776
+ * The same media footprint, broken down by {@link MediaFileKind} instead of
26777
+ * by camera — fleet-wide, or for one camera with `deviceId`.
26778
+ *
26779
+ * Separate from {@link getEventStoreFootprint} rather than a field on it:
26780
+ * the two answer different questions on different axes, the per-camera one
26781
+ * is what the management table renders on every open, and nothing should
26782
+ * pay for a per-kind pass to draw it. See
26783
+ * {@link EventMediaKindBreakdownSchema} for why `unaccounted*` exists —
26784
+ * `kinds` is enumerated, `totalBytes` is not, and the gap must be visible
26785
+ * to anyone sizing a deletion against it.
26786
+ */
26787
+ getEventMediaFootprintByKind: method(external_exports.object({ deviceId: external_exports.number().int().optional() }), EventMediaKindBreakdownSchema, {
26788
+ kind: "query",
26789
+ auth: "admin"
26790
+ }),
26791
+ /**
26757
26792
  * Cluster-wide prune of events older than `olderThanMs` (exclusive) across
26758
26793
  * every camera, deleting each event's media in lockstep. Logged to the
26759
26794
  * events ops-log with `reason` (default `'retention'`). Returns the summed
@@ -29497,6 +29532,20 @@ var storageCapability = {
29497
29532
  listProviders: method(external_exports.void(), external_exports.array(ProviderListEntrySchema).readonly()),
29498
29533
  testConfig: method(external_exports.object({
29499
29534
  providerId: external_exports.string(),
29535
+ /**
29536
+ * The location this config is an UNSAVED edit of, when there is one.
29537
+ *
29538
+ * `listLocations` replaces every declared secret with the redaction
29539
+ * sentinel, so the edit modal's form state holds the sentinel for any
29540
+ * credential the operator did not retype — and posting that here
29541
+ * without a way to resolve it makes the provider try to authenticate
29542
+ * as `__camstack_redacted__` and report the operator's own working
29543
+ * password as wrong. Given this id, the orchestrator restores each
29544
+ * sentinel from the stored config (same rule as `upsertLocation`)
29545
+ * before dispatching. Omitted by the "Add location" wizard, where
29546
+ * every value was typed just now and nothing is stored yet.
29547
+ */
29548
+ locationId: external_exports.string().optional(),
29500
29549
  config: external_exports.record(external_exports.string(), external_exports.unknown())
29501
29550
  }), external_exports.object({
29502
29551
  ok: external_exports.boolean(),
@@ -41957,6 +42006,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
41957
42006
  addonId: null,
41958
42007
  access: "view"
41959
42008
  },
42009
+ "pipelineAnalytics.getEventMediaFootprintByKind": {
42010
+ capName: "pipeline-analytics",
42011
+ capScope: "device",
42012
+ addonId: null,
42013
+ access: "view"
42014
+ },
41960
42015
  "pipelineAnalytics.getEventStoreFootprint": {
41961
42016
  capName: "pipeline-analytics",
41962
42017
  capScope: "device",
@@ -45622,6 +45677,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
45622
45677
  form: "single",
45623
45678
  optional: false
45624
45679
  }],
45680
+ "pipelineAnalytics.getEventMediaFootprintByKind": [{
45681
+ name: "deviceId",
45682
+ form: "single",
45683
+ optional: true
45684
+ }],
45625
45685
  "pipelineAnalytics.getGroup": [{
45626
45686
  name: "deviceId",
45627
45687
  form: "single",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-MYPVHFJL.js";
4
+ } from "./chunk-6X7D7D4Y.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-5FCVBL5M.js");
41
+ await import("./launcher-H2LQYCEY.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-5FCVBL5M.js");
86
+ await import("./launcher-H2LQYCEY.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-PJINOUDH.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-ABTN33LN.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-MYPVHFJL.js";
8
+ } from "./chunk-6X7D7D4Y.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-Keu5TDO7.js
23637
- var require_dist_Keu5TDO7 = __commonJS({
23638
- "../system/dist/dist-Keu5TDO7.js"(exports) {
23636
+ // ../system/dist/dist-CCIBlacf.js
23637
+ var require_dist_CCIBlacf = __commonJS({
23638
+ "../system/dist/dist-CCIBlacf.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -37094,6 +37094,25 @@ var require_dist_Keu5TDO7 = __commonJS({
37094
37094
  totalBytes: zod.z.number().int(),
37095
37095
  devices: zod.z.array(EventStoreDeviceFootprintSchema).readonly()
37096
37096
  });
37097
+ var EventMediaKindFootprintSchema = zod.z.object({
37098
+ kind: MediaFileKindEnum,
37099
+ /** Media rows of this kind. */
37100
+ rows: zod.z.number().int(),
37101
+ /** Bytes on disk held by those rows. */
37102
+ bytes: zod.z.number().int()
37103
+ });
37104
+ var EventMediaKindBreakdownSchema = zod.z.object({
37105
+ /** Every media row in scope, from one unfiltered aggregate. */
37106
+ totalRows: zod.z.number().int(),
37107
+ /** Every media byte in scope, from that same aggregate. */
37108
+ totalBytes: zod.z.number().int(),
37109
+ /** Per-kind footprint, ordered by bytes descending. */
37110
+ kinds: zod.z.array(EventMediaKindFootprintSchema).readonly(),
37111
+ /** `totalRows` minus the summed `kinds` rows — see the schema note. */
37112
+ unaccountedRows: zod.z.number().int(),
37113
+ /** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
37114
+ unaccountedBytes: zod.z.number().int()
37115
+ });
37097
37116
  var EventPruneCountsSchema = zod.z.object({
37098
37117
  motion: zod.z.number().int(),
37099
37118
  object: zod.z.number().int(),
@@ -37449,6 +37468,22 @@ var require_dist_Keu5TDO7 = __commonJS({
37449
37468
  auth: "admin"
37450
37469
  }),
37451
37470
  /**
37471
+ * The same media footprint, broken down by {@link MediaFileKind} instead of
37472
+ * by camera — fleet-wide, or for one camera with `deviceId`.
37473
+ *
37474
+ * Separate from {@link getEventStoreFootprint} rather than a field on it:
37475
+ * the two answer different questions on different axes, the per-camera one
37476
+ * is what the management table renders on every open, and nothing should
37477
+ * pay for a per-kind pass to draw it. See
37478
+ * {@link EventMediaKindBreakdownSchema} for why `unaccounted*` exists —
37479
+ * `kinds` is enumerated, `totalBytes` is not, and the gap must be visible
37480
+ * to anyone sizing a deletion against it.
37481
+ */
37482
+ getEventMediaFootprintByKind: method(zod.z.object({ deviceId: zod.z.number().int().optional() }), EventMediaKindBreakdownSchema, {
37483
+ kind: "query",
37484
+ auth: "admin"
37485
+ }),
37486
+ /**
37452
37487
  * Cluster-wide prune of events older than `olderThanMs` (exclusive) across
37453
37488
  * every camera, deleting each event's media in lockstep. Logged to the
37454
37489
  * events ops-log with `reason` (default `'retention'`). Returns the summed
@@ -40047,6 +40082,20 @@ var require_dist_Keu5TDO7 = __commonJS({
40047
40082
  listProviders: method(zod.z.void(), zod.z.array(ProviderListEntrySchema).readonly()),
40048
40083
  testConfig: method(zod.z.object({
40049
40084
  providerId: zod.z.string(),
40085
+ /**
40086
+ * The location this config is an UNSAVED edit of, when there is one.
40087
+ *
40088
+ * `listLocations` replaces every declared secret with the redaction
40089
+ * sentinel, so the edit modal's form state holds the sentinel for any
40090
+ * credential the operator did not retype — and posting that here
40091
+ * without a way to resolve it makes the provider try to authenticate
40092
+ * as `__camstack_redacted__` and report the operator's own working
40093
+ * password as wrong. Given this id, the orchestrator restores each
40094
+ * sentinel from the stored config (same rule as `upsertLocation`)
40095
+ * before dispatching. Omitted by the "Add location" wizard, where
40096
+ * every value was typed just now and nothing is stored yet.
40097
+ */
40098
+ locationId: zod.z.string().optional(),
40050
40099
  config: zod.z.record(zod.z.string(), zod.z.unknown())
40051
40100
  }), zod.z.object({
40052
40101
  ok: zod.z.boolean(),
@@ -53273,6 +53322,12 @@ var require_dist_Keu5TDO7 = __commonJS({
53273
53322
  addonId: null,
53274
53323
  access: "view"
53275
53324
  },
53325
+ "pipelineAnalytics.getEventMediaFootprintByKind": {
53326
+ capName: "pipeline-analytics",
53327
+ capScope: "device",
53328
+ addonId: null,
53329
+ access: "view"
53330
+ },
53276
53331
  "pipelineAnalytics.getEventStoreFootprint": {
53277
53332
  capName: "pipeline-analytics",
53278
53333
  capScope: "device",
@@ -56938,6 +56993,11 @@ var require_dist_Keu5TDO7 = __commonJS({
56938
56993
  form: "single",
56939
56994
  optional: false
56940
56995
  }],
56996
+ "pipelineAnalytics.getEventMediaFootprintByKind": [{
56997
+ name: "deviceId",
56998
+ form: "single",
56999
+ optional: true
57000
+ }],
56941
57001
  "pipelineAnalytics.getGroup": [{
56942
57002
  name: "deviceId",
56943
57003
  form: "single",
@@ -59147,7 +59207,7 @@ var require_alerts_addon = __commonJS({
59147
59207
  [Symbol.toStringTag]: { value: "Module" }
59148
59208
  });
59149
59209
  require_chunk_Cek0wNdY();
59150
- var require_dist10 = require_dist_Keu5TDO7();
59210
+ var require_dist10 = require_dist_CCIBlacf();
59151
59211
  function selectExpired(alerts, cutoffMs) {
59152
59212
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
59153
59213
  }
@@ -59966,7 +60026,7 @@ var require_console_logging = __commonJS({
59966
60026
  [Symbol.toStringTag]: { value: "Module" }
59967
60027
  });
59968
60028
  require_chunk_Cek0wNdY();
59969
- var require_dist10 = require_dist_Keu5TDO7();
60029
+ var require_dist10 = require_dist_CCIBlacf();
59970
60030
  var require_formatter = require_formatter_DqAKDlvN();
59971
60031
  var LEVEL_RANK = {
59972
60032
  debug: 0,
@@ -60060,7 +60120,7 @@ var require_core_blocks_addon = __commonJS({
60060
60120
  "use strict";
60061
60121
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
60062
60122
  var require_chunk = require_chunk_Cek0wNdY();
60063
- var require_dist10 = require_dist_Keu5TDO7();
60123
+ var require_dist10 = require_dist_CCIBlacf();
60064
60124
  var node_crypto = __require("crypto");
60065
60125
  var node_fs_promises = __require("fs/promises");
60066
60126
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -60957,11 +61017,11 @@ var require_core_blocks = __commonJS({
60957
61017
  }
60958
61018
  });
60959
61019
 
60960
- // ../system/dist/retired-settings-keys-BBohF-eC.js
60961
- var require_retired_settings_keys_BBohF_eC = __commonJS({
60962
- "../system/dist/retired-settings-keys-BBohF-eC.js"(exports) {
61020
+ // ../system/dist/retired-settings-keys-BxV3e2Km.js
61021
+ var require_retired_settings_keys_BxV3e2Km = __commonJS({
61022
+ "../system/dist/retired-settings-keys-BxV3e2Km.js"(exports) {
60963
61023
  "use strict";
60964
- var require_dist10 = require_dist_Keu5TDO7();
61024
+ var require_dist10 = require_dist_CCIBlacf();
60965
61025
  function settingsStoreIsAuthoritativeHere(env) {
60966
61026
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
60967
61027
  return raw === "" || raw === "hub";
@@ -63175,8 +63235,8 @@ var require_device_manager_addon = __commonJS({
63175
63235
  [Symbol.toStringTag]: { value: "Module" }
63176
63236
  });
63177
63237
  require_chunk_Cek0wNdY();
63178
- var require_dist10 = require_dist_Keu5TDO7();
63179
- var require_retired_settings_keys = require_retired_settings_keys_BBohF_eC();
63238
+ var require_dist10 = require_dist_CCIBlacf();
63239
+ var require_retired_settings_keys = require_retired_settings_keys_BxV3e2Km();
63180
63240
  var node_crypto = __require("crypto");
63181
63241
  var _camstack_types_node = require_node();
63182
63242
  var JOB_HISTORY = 20;
@@ -67989,7 +68049,7 @@ var require_hub_forwarder = __commonJS({
67989
68049
  [Symbol.toStringTag]: { value: "Module" }
67990
68050
  });
67991
68051
  require_chunk_Cek0wNdY();
67992
- var require_dist10 = require_dist_Keu5TDO7();
68052
+ var require_dist10 = require_dist_CCIBlacf();
67993
68053
  var require_formatter = require_formatter_DqAKDlvN();
67994
68054
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
67995
68055
  var HubForwarderDestination = class {
@@ -68126,7 +68186,7 @@ var require_liveness_monitor_addon = __commonJS({
68126
68186
  "use strict";
68127
68187
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
68128
68188
  require_chunk_Cek0wNdY();
68129
- var require_dist10 = require_dist_Keu5TDO7();
68189
+ var require_dist10 = require_dist_CCIBlacf();
68130
68190
  var NO_DEVICES = "liveness:no-devices";
68131
68191
  var ALL_OFFLINE = "liveness:all-devices-offline";
68132
68192
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -68316,7 +68376,7 @@ var require_local_auth_addon = __commonJS({
68316
68376
  [Symbol.toStringTag]: { value: "Module" }
68317
68377
  });
68318
68378
  var require_chunk = require_chunk_Cek0wNdY();
68319
- var require_dist10 = require_dist_Keu5TDO7();
68379
+ var require_dist10 = require_dist_CCIBlacf();
68320
68380
  var node_crypto = __require("crypto");
68321
68381
  node_crypto = require_chunk.__toESM(node_crypto);
68322
68382
  var crypto$1 = __require("crypto");
@@ -76129,7 +76189,7 @@ var require_loki_logging = __commonJS({
76129
76189
  [Symbol.toStringTag]: { value: "Module" }
76130
76190
  });
76131
76191
  require_chunk_Cek0wNdY();
76132
- var require_dist10 = require_dist_Keu5TDO7();
76192
+ var require_dist10 = require_dist_CCIBlacf();
76133
76193
  function sanitizeLabelName(raw) {
76134
76194
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
76135
76195
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -76694,7 +76754,7 @@ var require_native_metrics_addon = __commonJS({
76694
76754
  [Symbol.toStringTag]: { value: "Module" }
76695
76755
  });
76696
76756
  var require_chunk = require_chunk_Cek0wNdY();
76697
- var require_dist10 = require_dist_Keu5TDO7();
76757
+ var require_dist10 = require_dist_CCIBlacf();
76698
76758
  var node_fs_promises = __require("fs/promises");
76699
76759
  var node_child_process = __require("child_process");
76700
76760
  var node_util = __require("util");
@@ -79316,7 +79376,7 @@ var require_filesystem_storage_addon = __commonJS({
79316
79376
  [Symbol.toStringTag]: { value: "Module" }
79317
79377
  });
79318
79378
  var require_chunk = require_chunk_Cek0wNdY();
79319
- var require_dist10 = require_dist_Keu5TDO7();
79379
+ var require_dist10 = require_dist_CCIBlacf();
79320
79380
  var node_crypto = __require("crypto");
79321
79381
  var node_fs_promises = __require("fs/promises");
79322
79382
  var node_path = __require("path");
@@ -80432,8 +80492,8 @@ var require_sqlite_settings_addon = __commonJS({
80432
80492
  [Symbol.toStringTag]: { value: "Module" }
80433
80493
  });
80434
80494
  var require_chunk = require_chunk_Cek0wNdY();
80435
- var require_dist10 = require_dist_Keu5TDO7();
80436
- var require_retired_settings_keys = require_retired_settings_keys_BBohF_eC();
80495
+ var require_dist10 = require_dist_CCIBlacf();
80496
+ var require_retired_settings_keys = require_retired_settings_keys_BxV3e2Km();
80437
80497
  var node_crypto = __require("crypto");
80438
80498
  var node_fs = __require("fs");
80439
80499
  var node_module = __require("module");
@@ -82812,7 +82872,7 @@ var require_storage_orchestrator_addon = __commonJS({
82812
82872
  [Symbol.toStringTag]: { value: "Module" }
82813
82873
  });
82814
82874
  var require_chunk = require_chunk_Cek0wNdY();
82815
- var require_dist10 = require_dist_Keu5TDO7();
82875
+ var require_dist10 = require_dist_CCIBlacf();
82816
82876
  var node_crypto = __require("crypto");
82817
82877
  var node_fs_promises = __require("fs/promises");
82818
82878
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -83795,10 +83855,21 @@ var require_storage_orchestrator_addon = __commonJS({
83795
83855
  declareCollection: async (input) => (await engine()).declareCollection(input)
83796
83856
  };
83797
83857
  }
83798
- var EMPTY_SECRET_KEYS = /* @__PURE__ */ new Set();
83858
+ var FRAMEWORK_CONFIG_KEYS = /* @__PURE__ */ new Set([
83859
+ "basePath",
83860
+ "readOnly",
83861
+ "maxUsedGb",
83862
+ "minFreePercent"
83863
+ ]);
83799
83864
  function secretKeysOfProviderInfo(info) {
83800
83865
  return require_dist10.collectSecretConfigKeys(info.configSchema);
83801
83866
  }
83867
+ function secretKeysForConfig(config, declared) {
83868
+ if (declared !== void 0) return declared;
83869
+ const out = /* @__PURE__ */ new Set();
83870
+ for (const key of Object.keys(config)) if (!FRAMEWORK_CONFIG_KEYS.has(key)) out.add(key);
83871
+ return out;
83872
+ }
83802
83873
  function redactLocationConfig(config, secretKeys) {
83803
83874
  if (secretKeys.size === 0) return config;
83804
83875
  let touched = false;
@@ -84784,7 +84855,7 @@ var require_storage_orchestrator_addon = __commonJS({
84784
84855
  listLocationDeclarations: async () => service.listDeclarations(),
84785
84856
  upsertLocation: async (input) => {
84786
84857
  const stored = service.getLocationById(input.id);
84787
- const config = restoreRedactedSecrets(input.config, stored?.config, this.secretKeysFor(input.providerId));
84858
+ const config = restoreRedactedSecrets(input.config, stored?.config, this.secretKeysFor(input.providerId, stored?.config ?? {}));
84788
84859
  const saved = service.upsertLocation(config === input.config ? input : {
84789
84860
  ...input,
84790
84861
  config
@@ -84817,11 +84888,14 @@ var require_storage_orchestrator_addon = __commonJS({
84817
84888
  } });
84818
84889
  });
84819
84890
  },
84820
- testConfig: async ({ providerId, config }) => {
84891
+ testConfig: async ({ providerId, locationId, config }) => {
84892
+ const stored = locationId === void 0 ? void 0 : service.getLocationById(locationId);
84893
+ const base = stored?.providerId === providerId ? stored.config : void 0;
84894
+ const resolved = restoreRedactedSecrets(config, base, this.secretKeysFor(providerId, base ?? {}));
84821
84895
  const providers = getProviders();
84822
84896
  for (const p of providers) try {
84823
84897
  if ((await p.getProviderInfo()).providerId !== providerId) continue;
84824
- return p.testLocation({ config });
84898
+ return p.testLocation({ config: resolved });
84825
84899
  } catch (err) {
84826
84900
  return {
84827
84901
  ok: false,
@@ -85141,13 +85215,21 @@ var require_storage_orchestrator_addon = __commonJS({
85141
85215
  }
85142
85216
  return out;
85143
85217
  }
85144
- /** Declared secret config keys for a provider; empty when unknown. */
85145
- secretKeysFor(providerId) {
85146
- return this.secretKeysByProvider.get(providerId) ?? EMPTY_SECRET_KEYS;
85218
+ /**
85219
+ * What the provider's own schema declared secret, or `undefined` when this
85220
+ * node has never heard from that provider. The distinction is the whole
85221
+ * point — see `secretKeysForConfig`, which fails CLOSED on `undefined`.
85222
+ */
85223
+ declaredSecretKeys(providerId) {
85224
+ return this.secretKeysByProvider.get(providerId);
85225
+ }
85226
+ /** Which keys of a given stored config must never leave this process. */
85227
+ secretKeysFor(providerId, config) {
85228
+ return secretKeysForConfig(config, this.declaredSecretKeys(providerId));
85147
85229
  }
85148
85230
  /** A location with its provider's declared secrets replaced by the sentinel. */
85149
85231
  redacted(location) {
85150
- return redactLocation(location, this.secretKeysFor(location.providerId));
85232
+ return redactLocation(location, this.secretKeysFor(location.providerId, location.config));
85151
85233
  }
85152
85234
  /**
85153
85235
  * Is this location backed by a provider that serves a genuine local
@@ -85387,7 +85469,7 @@ var require_system_config_addon = __commonJS({
85387
85469
  [Symbol.toStringTag]: { value: "Module" }
85388
85470
  });
85389
85471
  require_chunk_Cek0wNdY();
85390
- var require_dist10 = require_dist_Keu5TDO7();
85472
+ var require_dist10 = require_dist_CCIBlacf();
85391
85473
  var SECTION_TITLES = {
85392
85474
  server: "Server",
85393
85475
  auth: "Authentication"
@@ -103448,7 +103530,7 @@ var require_winston_logging = __commonJS({
103448
103530
  [Symbol.toStringTag]: { value: "Module" }
103449
103531
  });
103450
103532
  var require_chunk = require_chunk_Cek0wNdY();
103451
- var require_dist10 = require_dist_Keu5TDO7();
103533
+ var require_dist10 = require_dist_CCIBlacf();
103452
103534
  var require_formatter = require_formatter_DqAKDlvN();
103453
103535
  var node_path = __require("path");
103454
103536
  node_path = require_chunk.__toESM(node_path);
@@ -105391,9 +105473,9 @@ var require_event_category_BaEgqJNv = __commonJS({
105391
105473
  }
105392
105474
  });
105393
105475
 
105394
- // ../types/dist/sleep-C3AniWy-.js
105395
- var require_sleep_C3AniWy = __commonJS({
105396
- "../types/dist/sleep-C3AniWy-.js"(exports) {
105476
+ // ../types/dist/sleep-D5821NGq.js
105477
+ var require_sleep_D5821NGq = __commonJS({
105478
+ "../types/dist/sleep-D5821NGq.js"(exports) {
105397
105479
  "use strict";
105398
105480
  var require_event_category = require_event_category_BaEgqJNv();
105399
105481
  var zod = require_zod();
@@ -108084,6 +108166,7 @@ var require_sleep_C3AniWy = __commonJS({
108084
108166
  deleteTracks: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deleteTracks", "mutation", input),
108085
108167
  setTrackFlags: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "setTrackFlags", "mutation", input),
108086
108168
  getEventStoreFootprint: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventStoreFootprint", "query", input),
108169
+ getEventMediaFootprintByKind: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventMediaFootprintByKind", "query", input),
108087
108170
  pruneEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneEvents", "mutation", input),
108088
108171
  deleteDeviceEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deleteDeviceEvents", "mutation", input),
108089
108172
  pauseForStorageMigration: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pauseForStorageMigration", "mutation", input),
@@ -109060,7 +109143,7 @@ var require_addon = __commonJS({
109060
109143
  "use strict";
109061
109144
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
109062
109145
  var require_event_category = require_event_category_BaEgqJNv();
109063
- var require_sleep = require_sleep_C3AniWy();
109146
+ var require_sleep = require_sleep_D5821NGq();
109064
109147
  var require_err_msg = require_err_msg_COpsHMw2();
109065
109148
  var CAP_INPUT_DEFAULTS = Object.freeze({
109066
109149
  "addons": { "getLogs": { "limit": 100 } },
@@ -115942,12 +116025,12 @@ var require_dist2 = __commonJS({
115942
116025
  }
115943
116026
  });
115944
116027
 
115945
- // ../system/dist/manifest-system-deps-DYv4ZPo2.js
115946
- var require_manifest_system_deps_DYv4ZPo2 = __commonJS({
115947
- "../system/dist/manifest-system-deps-DYv4ZPo2.js"(exports) {
116028
+ // ../system/dist/manifest-system-deps-alrkBKVQ.js
116029
+ var require_manifest_system_deps_alrkBKVQ = __commonJS({
116030
+ "../system/dist/manifest-system-deps-alrkBKVQ.js"(exports) {
115948
116031
  "use strict";
115949
116032
  var require_chunk = require_chunk_Cek0wNdY();
115950
- require_dist_Keu5TDO7();
116033
+ require_dist_CCIBlacf();
115951
116034
  var node_crypto = __require("crypto");
115952
116035
  node_crypto = require_chunk.__toESM(node_crypto);
115953
116036
  var _camstack_types_node = require_node();
@@ -127976,7 +128059,7 @@ var require_dist3 = __commonJS({
127976
128059
  "use strict";
127977
128060
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
127978
128061
  var require_chunk = require_chunk_Cek0wNdY();
127979
- var require_dist10 = require_dist_Keu5TDO7();
128062
+ var require_dist10 = require_dist_CCIBlacf();
127980
128063
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
127981
128064
  require_alerts();
127982
128065
  var require_formatter = require_formatter_DqAKDlvN();
@@ -128002,7 +128085,7 @@ var require_dist3 = __commonJS({
128002
128085
  var require_builtins_winston_logging_index = require_winston_logging();
128003
128086
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
128004
128087
  var require_tls$1 = require_tls_BxQlomxd();
128005
- var require_manifest_system_deps = require_manifest_system_deps_DYv4ZPo2();
128088
+ var require_manifest_system_deps = require_manifest_system_deps_alrkBKVQ();
128006
128089
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
128007
128090
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
128008
128091
  var zod = require_zod();
@@ -208826,7 +208909,7 @@ var require_dist4 = __commonJS({
208826
208909
  "use strict";
208827
208910
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
208828
208911
  var require_event_category = require_event_category_BaEgqJNv();
208829
- var require_sleep = require_sleep_C3AniWy();
208912
+ var require_sleep = require_sleep_D5821NGq();
208830
208913
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
208831
208914
  var require_enums2 = require_enums();
208832
208915
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -222975,6 +223058,25 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
222975
223058
  totalBytes: zod.z.number().int(),
222976
223059
  devices: zod.z.array(EventStoreDeviceFootprintSchema).readonly()
222977
223060
  });
223061
+ var EventMediaKindFootprintSchema = zod.z.object({
223062
+ kind: MediaFileKindEnum,
223063
+ /** Media rows of this kind. */
223064
+ rows: zod.z.number().int(),
223065
+ /** Bytes on disk held by those rows. */
223066
+ bytes: zod.z.number().int()
223067
+ });
223068
+ var EventMediaKindBreakdownSchema = zod.z.object({
223069
+ /** Every media row in scope, from one unfiltered aggregate. */
223070
+ totalRows: zod.z.number().int(),
223071
+ /** Every media byte in scope, from that same aggregate. */
223072
+ totalBytes: zod.z.number().int(),
223073
+ /** Per-kind footprint, ordered by bytes descending. */
223074
+ kinds: zod.z.array(EventMediaKindFootprintSchema).readonly(),
223075
+ /** `totalRows` minus the summed `kinds` rows — see the schema note. */
223076
+ unaccountedRows: zod.z.number().int(),
223077
+ /** `totalBytes` minus the summed `kinds` bytes — see the schema note. */
223078
+ unaccountedBytes: zod.z.number().int()
223079
+ });
222978
223080
  var EventPruneCountsSchema = zod.z.object({
222979
223081
  motion: zod.z.number().int(),
222980
223082
  object: zod.z.number().int(),
@@ -223330,6 +223432,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
223330
223432
  auth: "admin"
223331
223433
  }),
223332
223434
  /**
223435
+ * The same media footprint, broken down by {@link MediaFileKind} instead of
223436
+ * by camera — fleet-wide, or for one camera with `deviceId`.
223437
+ *
223438
+ * Separate from {@link getEventStoreFootprint} rather than a field on it:
223439
+ * the two answer different questions on different axes, the per-camera one
223440
+ * is what the management table renders on every open, and nothing should
223441
+ * pay for a per-kind pass to draw it. See
223442
+ * {@link EventMediaKindBreakdownSchema} for why `unaccounted*` exists —
223443
+ * `kinds` is enumerated, `totalBytes` is not, and the gap must be visible
223444
+ * to anyone sizing a deletion against it.
223445
+ */
223446
+ getEventMediaFootprintByKind: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().optional() }), EventMediaKindBreakdownSchema, {
223447
+ kind: "query",
223448
+ auth: "admin"
223449
+ }),
223450
+ /**
223333
223451
  * Cluster-wide prune of events older than `olderThanMs` (exclusive) across
223334
223452
  * every camera, deleting each event's media in lockstep. Logged to the
223335
223453
  * events ops-log with `reason` (default `'retention'`). Returns the summed
@@ -226092,6 +226210,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
226092
226210
  listProviders: require_sleep.method(zod.z.void(), zod.z.array(ProviderListEntrySchema).readonly()),
226093
226211
  testConfig: require_sleep.method(zod.z.object({
226094
226212
  providerId: zod.z.string(),
226213
+ /**
226214
+ * The location this config is an UNSAVED edit of, when there is one.
226215
+ *
226216
+ * `listLocations` replaces every declared secret with the redaction
226217
+ * sentinel, so the edit modal's form state holds the sentinel for any
226218
+ * credential the operator did not retype — and posting that here
226219
+ * without a way to resolve it makes the provider try to authenticate
226220
+ * as `__camstack_redacted__` and report the operator's own working
226221
+ * password as wrong. Given this id, the orchestrator restores each
226222
+ * sentinel from the stored config (same rule as `upsertLocation`)
226223
+ * before dispatching. Omitted by the "Add location" wizard, where
226224
+ * every value was typed just now and nothing is stored yet.
226225
+ */
226226
+ locationId: zod.z.string().optional(),
226095
226227
  config: zod.z.record(zod.z.string(), zod.z.unknown())
226096
226228
  }), zod.z.object({
226097
226229
  ok: zod.z.boolean(),
@@ -242263,6 +242395,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
242263
242395
  addonId: null,
242264
242396
  access: "view"
242265
242397
  },
242398
+ "pipelineAnalytics.getEventMediaFootprintByKind": {
242399
+ capName: "pipeline-analytics",
242400
+ capScope: "device",
242401
+ addonId: null,
242402
+ access: "view"
242403
+ },
242266
242404
  "pipelineAnalytics.getEventStoreFootprint": {
242267
242405
  capName: "pipeline-analytics",
242268
242406
  capScope: "device",
@@ -246186,6 +246324,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246186
246324
  form: "single",
246187
246325
  optional: false
246188
246326
  }],
246327
+ "pipelineAnalytics.getEventMediaFootprintByKind": [{
246328
+ name: "deviceId",
246329
+ form: "single",
246330
+ optional: true
246331
+ }],
246189
246332
  "pipelineAnalytics.getGroup": [{
246190
246333
  name: "deviceId",
246191
246334
  form: "single",
@@ -251291,6 +251434,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
251291
251434
  exports.MaskShapeKindSchema = MaskShapeKindSchema;
251292
251435
  exports.MaskShapeSchema = MaskShapeSchema;
251293
251436
  exports.MediaFileInfoSchema = MediaFileInfoSchema;
251437
+ exports.MediaFileKindEnum = MediaFileKindEnum;
251294
251438
  exports.MediaFileRefSchema = MediaFileRefSchema;
251295
251439
  exports.MediaFileSchema = MediaFileSchema;
251296
251440
  exports.MediaPlayerRepeatSchema = MediaPlayerRepeatSchema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.67",
3
+ "version": "1.2.68",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",