@camstack/system 1.2.438 → 1.2.440

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.
Files changed (120) hide show
  1. package/dist/addon-runner.js +743 -79
  2. package/dist/addon-runner.mjs +743 -79
  3. package/dist/addon-utils.js +1 -1
  4. package/dist/addon-utils.mjs +1 -1
  5. package/dist/{agent-https-BZIwS4xF.js → agent-https-DlpTMDqA.js} +252 -22
  6. package/dist/{agent-https-BPfHrI4c.mjs → agent-https-U0d4uvn2.mjs} +211 -23
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  10. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  11. package/dist/builtins/alerts/alerts.addon.js +1 -1
  12. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  13. package/dist/builtins/autotrack/index.js +1 -1
  14. package/dist/builtins/autotrack/index.mjs +1 -1
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  16. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  17. package/dist/builtins/calendars/calendars.addon.js +1 -1
  18. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  19. package/dist/builtins/camera-grid/index.js +1 -1
  20. package/dist/builtins/camera-grid/index.mjs +1 -1
  21. package/dist/builtins/composer/composer.addon.js +2 -2
  22. package/dist/builtins/composer/composer.addon.mjs +2 -2
  23. package/dist/builtins/console-logging/index.js +1 -1
  24. package/dist/builtins/console-logging/index.mjs +1 -1
  25. package/dist/builtins/core-blocks/block-settings-store.d.ts +1 -1
  26. package/dist/builtins/core-blocks/core-blocks.addon.js +77 -11
  27. package/dist/builtins/core-blocks/core-blocks.addon.mjs +77 -12
  28. package/dist/builtins/core-blocks/index.mjs +1 -1
  29. package/dist/builtins/device-manager/device-manager.addon.js +197 -60
  30. package/dist/builtins/device-manager/device-manager.addon.mjs +196 -61
  31. package/dist/builtins/device-manager/device-removal-hooks.d.ts +0 -11
  32. package/dist/builtins/device-manager/device-tombstone-store.d.ts +12 -2
  33. package/dist/builtins/hub-forwarder/index.js +1 -1
  34. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  35. package/dist/builtins/keychain/index.js +29 -11
  36. package/dist/builtins/keychain/index.mjs +29 -11
  37. package/dist/builtins/keychain/keychain-service.d.ts +8 -0
  38. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  39. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  40. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  41. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  42. package/dist/builtins/local-network/local-network.addon.js +7 -2
  43. package/dist/builtins/local-network/local-network.addon.mjs +7 -2
  44. package/dist/builtins/loki-logging/index.js +1 -1
  45. package/dist/builtins/loki-logging/index.mjs +1 -1
  46. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  47. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  48. package/dist/builtins/platform-probe/index.js +1 -1
  49. package/dist/builtins/platform-probe/index.mjs +1 -1
  50. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  51. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  52. package/dist/builtins/snapshot/index.js +1 -1
  53. package/dist/builtins/snapshot/index.mjs +1 -1
  54. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  55. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  56. package/dist/builtins/sqlite-storage/index.js +1 -1
  57. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  58. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +38 -7
  59. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +69 -3
  60. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +69 -3
  61. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +31 -0
  62. package/dist/builtins/storage-orchestrator/hub-settings-forward.d.ts +3 -3
  63. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +4 -4
  64. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +4 -4
  65. package/dist/builtins/system-config/system-config.addon.js +4 -4
  66. package/dist/builtins/system-config/system-config.addon.mjs +285 -285
  67. package/dist/builtins/winston-logging/index.js +1 -1
  68. package/dist/builtins/winston-logging/index.mjs +1 -1
  69. package/dist/{composition-sources-DpHGCjdL.mjs → composition-sources-CS0D7imL.mjs} +1 -1
  70. package/dist/{composition-sources-DI3Z83vG.js → composition-sources-cBG8fBTu.js} +1 -1
  71. package/dist/{constants-DQK705Sb.mjs → constants-CIzPjw7L.mjs} +1 -1
  72. package/dist/{constants-wkcn5Ij3.js → constants-CRI3QzT4.js} +1 -1
  73. package/dist/{device-ca-DvIZjXIl.mjs → device-ca-DLKXYseS.mjs} +2 -2
  74. package/dist/{device-ca-BSvkXqyI.js → device-ca-DNHjts4_.js} +2 -2
  75. package/dist/{dist-Dc8GKC5H.mjs → dist-9fcsrFU3.mjs} +271 -32
  76. package/dist/{dist-GgG-7amw.js → dist-BKhlcYz6.js} +288 -31
  77. package/dist/file-host-worker.js +1 -1
  78. package/dist/file-host-worker.mjs +1 -1
  79. package/dist/{hub-mdns-ciao-CBLvq2oj.js → hub-mdns-ciao-3Zc9G9MS.js} +377 -69
  80. package/dist/{hub-mdns-ciao-DMlQTdPU.mjs → hub-mdns-ciao-Dy2YjRqC.mjs} +344 -72
  81. package/dist/index.js +372 -339
  82. package/dist/index.mjs +361 -341
  83. package/dist/kernel/addon-settings-store.d.ts +43 -0
  84. package/dist/kernel/config-manager.d.ts +0 -19
  85. package/dist/kernel/device-settings-store.d.ts +74 -0
  86. package/dist/kernel/legacy-blob-guard.d.ts +58 -0
  87. package/dist/kernel/moleculer/runner-addon-settings.d.ts +34 -0
  88. package/dist/kernel/moleculer/runner-device-settings.d.ts +39 -0
  89. package/dist/kernel/prefix-walk.d.ts +39 -0
  90. package/dist/kernel/sections-store.d.ts +20 -0
  91. package/dist/kernel/settings-door-view.d.ts +2 -2
  92. package/dist/kernel/settings-view-types.d.ts +5 -30
  93. package/dist/kernel/store-settings-view.d.ts +0 -3
  94. package/dist/{lib-NNxHSOIE.js → lib-8oZrELLm.js} +1 -1
  95. package/dist/{lib-BeGzVQcd.mjs → lib-DK38ompL.mjs} +1 -1
  96. package/dist/prefix-range-D_KueXbQ.js +27 -0
  97. package/dist/prefix-range-Dl0znowN.mjs +22 -0
  98. package/dist/prefix-walk-DAOBSyH1.mjs +88 -0
  99. package/dist/prefix-walk-Dv6MLZlM.js +99 -0
  100. package/dist/{restore-archive-CTRz8v9o.js → restore-archive-49aZwkp8.js} +1 -1
  101. package/dist/{restore-archive-DPg9duVY.mjs → restore-archive-DgvDecXM.mjs} +82 -82
  102. package/dist/{retired-settings-keys-Is0zO8gX.mjs → retired-settings-keys-Bhwe4ymb.mjs} +2 -2
  103. package/dist/{retired-settings-keys-Dr_4lfKu.js → retired-settings-keys-D_VwZiDt.js} +10 -4
  104. package/dist/tls/agent-https.d.ts +2 -2
  105. package/dist/tls/boot-tls.d.ts +6 -0
  106. package/dist/tls/cert-evaluation.d.ts +1 -1
  107. package/dist/tls/cert-issue.d.ts +5 -1
  108. package/dist/tls/cert-manager.d.ts +18 -0
  109. package/dist/tls/cert-name-constraints.d.ts +53 -0
  110. package/dist/tls/index.d.ts +5 -4
  111. package/dist/tls/tls-actions.d.ts +27 -7
  112. package/dist/tls/tls-status.d.ts +22 -0
  113. package/dist/tls/uploaded-cert.d.ts +36 -4
  114. package/dist/{wal-maintenance-Bx3lcVA7.mjs → wal-maintenance-BZGmF-3U.mjs} +0 -0
  115. package/dist/{wal-maintenance-mjB2i-VR.js → wal-maintenance-C041zn6V.js} +0 -0
  116. package/dist/{x509.es-r7Ht1thA.js → x509.es-C4cOo48M.js} +36 -0
  117. package/dist/{x509.es-CDvj67p1.mjs → x509.es-DK__ETIe.mjs} +1 -1
  118. package/package.json +7 -2
  119. package/dist/{custom-action-registry-Bf_YnagS.js → custom-action-registry-BKmoaqG0.js} +1 -1
  120. package/dist/{custom-action-registry-BQnbN0DP.mjs → custom-action-registry-CyUuhATc.mjs} +1 -1
@@ -1,5 +1,7 @@
1
- import { Bt as enumerateItemArrayFields, C as DAY_NAMES, Dn as parseStreamParamsFormPatch, Dr as errMsg, Er as DeviceType, Et as createDeviceExtensionProvider, Ft as deviceExtensionCapability, Ir as SECRET_CLEAR, It as deviceManagerCapability, Lr as WELL_KNOWN_TAB_MAP, Lt as deviceStateCapability, N as FieldClaimModeSchema, Or as BaseAddon, P as FieldClaimSchema, Qr as isDeviceConfigCap, Rt as deviceStatusCapability, Tr as DeviceRole, Un as runtimeStatePolicyFor, Ur as collectZodSecretPaths, V as MINUTES_PER_DAY, Vt as enumerateSchemaFields, Wt as expandContainer, Xt as formatMinutes, Yn as siteZoneKey, _i as transformSecretWrite, c as CAMERA_SWITCH_ORDER, di as resolveSecretMarkers, ei as isKeychainStoredField, gi as toSecretFieldView, gt as canonicalIconKey, j as DeviceStatusSchema, jt as defineExtensionSlotProvider, ln as legacyAutoLinkIds, mi as sleep$1, ni as isSecretMarker, pi as secretTreeFromPaths, pn as locationIconKey, pt as buildStreamParamsConfigSchema, q as STREAM_PROFILE_META, r as ALL_CAPABILITY_DEFINITIONS, ri as isSecretMarkerLike, ti as isSecretClear, u as CAP_NAMES_WITH_STATUS, vi as userError, wn as normalizeUnit, wr as DeviceFeature, yi as EventCategory } from "../../dist-Dc8GKC5H.mjs";
2
- import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-Is0zO8gX.mjs";
1
+ import { Ar as errMsg, Br as WELL_KNOWN_TAB_MAP, Bt as deviceStatusCapability, C as DAY_NAMES, Dr as DeviceFeature, En as normalizeUnit, Gn as runtimeStatePolicyFor, Ht as enumerateItemArrayFields, Kr as collectZodSecretPaths, Kt as expandContainer, Lt as deviceExtensionCapability, N as FieldClaimModeSchema, Nt as defineExtensionSlotProvider, Or as DeviceRole, Ot as createDeviceExtensionProvider, P as FieldClaimSchema, Qt as formatMinutes, Rt as deviceManagerCapability, Si as EventCategory, Ut as enumerateSchemaFields, V as MINUTES_PER_DAY, Y as STREAM_PROFILE_META, Zn as siteZoneKey, _i as sleep$1, ai as isSecretMarker, bi as transformSecretWrite, c as CAMERA_SWITCH_ORDER, dn as legacyAutoLinkIds, gi as secretTreeFromPaths, hn as locationIconKey, ht as buildStreamParamsConfigSchema, ii as isSecretClear, j as DeviceStatusSchema, jr as BaseAddon, kn as parseStreamParamsFormPatch, kr as DeviceType, mi as resolveSecretMarkers, oi as isSecretMarkerLike, r as ALL_CAPABILITY_DEFINITIONS, ri as isKeychainStoredField, ti as isDeviceConfigCap, u as CAP_NAMES_WITH_STATUS, vt as canonicalIconKey, xi as userError, yi as toSecretFieldView, zr as SECRET_CLEAR, zt as deviceStateCapability } from "../../dist-9fcsrFU3.mjs";
2
+ import { t as prefixRange } from "../../prefix-range-Dl0znowN.mjs";
3
+ import { t as loadPrefixed } from "../../prefix-walk-DAOBSyH1.mjs";
4
+ import { r as purgeRetiredSettingsRows } from "../../retired-settings-keys-Bhwe4ymb.mjs";
3
5
  import { z } from "zod";
4
6
  import { randomUUID } from "node:crypto";
5
7
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
@@ -2725,30 +2727,13 @@ async function listPersistedByAddon(pctx, input) {
2725
2727
  return saved;
2726
2728
  }
2727
2729
  /**
2728
- * Every requested device's persisted config, in as few store round trips as the
2729
- * settings view allows.
2730
- *
2731
- * One call when the view can batch (the in-process door, which keys
2732
- * `addon-device-settings` by `<addonId>:<deviceId>.` and answers a whole addon
2733
- * with one indexed range scan). Otherwise the per-device form, unchanged — a
2734
- * fallback and not a silent downgrade: `readDeviceStoreBatch` is optional
2735
- * precisely because a forked addon's view has nothing to batch, and refusing
2736
- * would break the only implementation that cannot comply.
2737
- *
2738
- * A read that THROWS yields `{}` for that device rather than failing the whole
2739
- * listing: one unreadable settings row must not make the fleet unlistable.
2730
+ * Every requested device's persisted config in ONE store round trip (D870). A
2731
+ * store that cannot be asked THROWS and the listing fails with it: an
2732
+ * unreadable row is not a device with no settings (D49).
2740
2733
  */
2741
2734
  async function readDeviceConfigs(pctx, deviceIds) {
2742
2735
  if (deviceIds.length === 0) return /* @__PURE__ */ new Map();
2743
- const batch = pctx.settings.readDeviceStoreBatch;
2744
- if (batch !== void 0) return batch.call(pctx.settings, deviceIds);
2745
- const out = /* @__PURE__ */ new Map();
2746
- for (const id of deviceIds) try {
2747
- out.set(id, await pctx.settings.readDeviceStore(id));
2748
- } catch {
2749
- out.set(id, {});
2750
- }
2751
- return out;
2736
+ return pctx.settings.readDeviceStoreBatch(deviceIds);
2752
2737
  }
2753
2738
  async function listAll(pctx, input) {
2754
2739
  const ownerFilter = Reflect.get(input, "addonId");
@@ -4851,6 +4836,170 @@ function createDeviceManagerExtensionProvider(pctx) {
4851
4836
  });
4852
4837
  }
4853
4838
  //#endregion
4839
+ //#region src/kernel/device-settings-store.ts
4840
+ /** The collection every addon's per-device settings share. Named nowhere else. */
4841
+ var DEVICE_SETTINGS_COLLECTION = "addon-device-settings";
4842
+ function scopeOf(addonId, deviceId) {
4843
+ return `${addonId}:${String(deviceId)}.`;
4844
+ }
4845
+ function assertDeviceId(deviceId) {
4846
+ if (!Number.isInteger(deviceId) || deviceId <= 0) throw new Error(`device settings: "${String(deviceId)}" is not a device id`);
4847
+ }
4848
+ function deviceIdOfSuffix(suffix) {
4849
+ const dot = suffix.indexOf(".");
4850
+ if (dot <= 0) return null;
4851
+ const id = Number(suffix.slice(0, dot));
4852
+ return Number.isInteger(id) && id > 0 ? id : null;
4853
+ }
4854
+ /** Every field row of one device scope, or a throw. */
4855
+ async function readScope(door, addonId, deviceId) {
4856
+ return loadPrefixed(door, DEVICE_SETTINGS_COLLECTION, scopeOf(addonId, deviceId));
4857
+ }
4858
+ function createDeviceSettingsStore(door, addonId) {
4859
+ return {
4860
+ async read(deviceId) {
4861
+ try {
4862
+ assertDeviceId(deviceId);
4863
+ const value = await readScope(door, addonId, deviceId);
4864
+ return Object.keys(value).length === 0 ? { kind: "absent" } : {
4865
+ kind: "present",
4866
+ value
4867
+ };
4868
+ } catch (err) {
4869
+ return {
4870
+ kind: "unreadable",
4871
+ error: err instanceof Error ? err.message : String(err)
4872
+ };
4873
+ }
4874
+ },
4875
+ async readBatch(deviceIds) {
4876
+ const out = /* @__PURE__ */ new Map();
4877
+ if (deviceIds.length === 0) return out;
4878
+ for (const id of deviceIds) out.set(id, {});
4879
+ const wanted = new Set(deviceIds);
4880
+ const all = await loadPrefixed(door, DEVICE_SETTINGS_COLLECTION, `${addonId}:`);
4881
+ for (const [suffix, value] of Object.entries(all)) {
4882
+ const id = deviceIdOfSuffix(suffix);
4883
+ if (id === null || !wanted.has(id)) continue;
4884
+ const blob = out.get(id);
4885
+ if (blob !== void 0) blob[suffix.slice(suffix.indexOf(".") + 1)] = value;
4886
+ }
4887
+ return out;
4888
+ },
4889
+ async listIds() {
4890
+ const all = await loadPrefixed(door, DEVICE_SETTINGS_COLLECTION, `${addonId}:`, () => null);
4891
+ const ids = /* @__PURE__ */ new Set();
4892
+ for (const suffix of Object.keys(all)) {
4893
+ const id = deviceIdOfSuffix(suffix);
4894
+ if (id !== null) ids.add(id);
4895
+ }
4896
+ return [...ids].toSorted((a, b) => a - b);
4897
+ },
4898
+ async merge(deviceId, patch) {
4899
+ assertDeviceId(deviceId);
4900
+ const scope = scopeOf(addonId, deviceId);
4901
+ const records = [];
4902
+ const removed = [];
4903
+ for (const [key, value] of Object.entries(patch)) if (value === void 0) removed.push(`${scope}${key}`);
4904
+ else records.push({
4905
+ id: `${scope}${key}`,
4906
+ data: {
4907
+ addonId,
4908
+ deviceId: String(deviceId),
4909
+ key,
4910
+ value
4911
+ }
4912
+ });
4913
+ if (records.length === 0 && removed.length === 0) return;
4914
+ await door.transact({ ops: [...removed.length > 0 ? [{
4915
+ op: "deleteWhere",
4916
+ collection: DEVICE_SETTINGS_COLLECTION,
4917
+ filter: { whereIn: { id: removed } }
4918
+ }] : [], ...records.length > 0 ? [{
4919
+ op: "upsertMany",
4920
+ collection: DEVICE_SETTINGS_COLLECTION,
4921
+ conflict: ["id"],
4922
+ records
4923
+ }] : []] });
4924
+ },
4925
+ async clear(deviceId) {
4926
+ assertDeviceId(deviceId);
4927
+ const range = prefixRange(scopeOf(addonId, deviceId));
4928
+ if (range === null) throw new Error(`device settings: no id range for addon "${addonId}"`);
4929
+ await door.deleteWhere({
4930
+ collection: DEVICE_SETTINGS_COLLECTION,
4931
+ filter: { whereBetween: { id: [range.lo, range.hi] } }
4932
+ });
4933
+ }
4934
+ };
4935
+ }
4936
+ /** The `Record` form of a read: `{}` for a store that answered with no row, a THROW for one that did not. */
4937
+ async function readDeviceOrThrow(store, deviceId) {
4938
+ const read = await store.read(deviceId);
4939
+ switch (read.kind) {
4940
+ case "present": return { ...read.value };
4941
+ case "absent": return {};
4942
+ case "unreadable": throw new Error(`device settings of ${String(deviceId)} could not be read: ${read.error}`);
4943
+ }
4944
+ }
4945
+ /**
4946
+ * Remove a device's rows for EVERY addon, in one statement (D865's central
4947
+ * delete). Matched on the device id each row carries, so no addon needs a
4948
+ * handler. Returns how many rows went.
4949
+ */
4950
+ async function clearDeviceSettings(door, deviceId) {
4951
+ assertDeviceId(deviceId);
4952
+ const { deleted } = await door.deleteWhere({
4953
+ collection: DEVICE_SETTINGS_COLLECTION,
4954
+ filter: { where: { deviceId: String(deviceId) } }
4955
+ });
4956
+ return deleted;
4957
+ }
4958
+ /** Rows one page of the scope walk asks for. */
4959
+ var SCOPE_PAGE_ROWS = 1e3;
4960
+ /** Pages the walk may take before it refuses (a bound, never a silent cut). */
4961
+ var SCOPE_PAGE_BUDGET = 512;
4962
+ /** Above every id: ids are ASCII. */
4963
+ var SCOPE_TAIL = "";
4964
+ /**
4965
+ * Every (addon, device) pair holding rows, across all addons - the admin
4966
+ * "deleted devices" listing. A keyset walk by primary key (never one query cut
4967
+ * at a row cap): a read that cannot be completed THROWS.
4968
+ */
4969
+ async function listDeviceSettingsScopes(door) {
4970
+ const seen = /* @__PURE__ */ new Map();
4971
+ let cursor = "";
4972
+ for (let page = 0;; page++) {
4973
+ if (page >= SCOPE_PAGE_BUDGET) throw new Error(`device settings scopes: more than ${SCOPE_PAGE_BUDGET} pages - refusing a partial list`);
4974
+ const rows = await door.query({
4975
+ collection: DEVICE_SETTINGS_COLLECTION,
4976
+ filter: {
4977
+ whereBetween: { id: [cursor, SCOPE_TAIL] },
4978
+ orderBy: {
4979
+ field: "id",
4980
+ direction: "asc"
4981
+ },
4982
+ limit: SCOPE_PAGE_ROWS
4983
+ }
4984
+ });
4985
+ for (const row of rows) {
4986
+ const addonId = row.data["addonId"];
4987
+ const raw = row.data["deviceId"];
4988
+ if (typeof addonId !== "string" || typeof raw !== "string") continue;
4989
+ const deviceId = Number(raw);
4990
+ if (!Number.isInteger(deviceId) || deviceId <= 0) continue;
4991
+ seen.set(`${addonId}:${deviceId}`, {
4992
+ deviceId,
4993
+ addonId
4994
+ });
4995
+ }
4996
+ const last = rows[rows.length - 1];
4997
+ if (rows.length < SCOPE_PAGE_ROWS || last === void 0) return [...seen.values()];
4998
+ if (last.id === cursor) throw new Error(`device settings scopes: no progress at "${last.id}"`);
4999
+ cursor = last.id;
5000
+ }
5001
+ }
5002
+ //#endregion
4854
5003
  //#region src/builtins/device-manager/migration-refused.ts
4855
5004
  /**
4856
5005
  * A migration step that REFUSED with nothing moved.
@@ -5783,41 +5932,16 @@ async function cleanupDeletedDevicesData(deps, input) {
5783
5932
  unreachable: [...unreachable]
5784
5933
  };
5785
5934
  }
5786
- /** The settings-store collection every addon's per-device settings share. */
5787
- var ADDON_DEVICE_SETTINGS_COLLECTION = "addon-device-settings";
5788
- /** The engine's hard ceiling on one read; a result this long may be a truncated one. */
5789
- var SCOPE_READ_LIMIT = 2e4;
5790
5935
  /** Scope access over the settings store; undefined when the store is unavailable. */
5791
5936
  function settingsScopes(store) {
5792
5937
  if (store === void 0) return void 0;
5938
+ const door = {
5939
+ query: (input) => store.query.query(input),
5940
+ deleteWhere: (input) => store.deleteWhere.mutate(input)
5941
+ };
5793
5942
  return {
5794
- list: async () => {
5795
- const rows = await store.query.query({
5796
- collection: ADDON_DEVICE_SETTINGS_COLLECTION,
5797
- filter: { limit: SCOPE_READ_LIMIT }
5798
- });
5799
- if (rows.length >= SCOPE_READ_LIMIT) throw new Error(`the settings read returned ${rows.length} rows — possibly truncated`);
5800
- const seen = /* @__PURE__ */ new Map();
5801
- for (const row of rows) {
5802
- const addonId = row.data["addonId"];
5803
- const raw = row.data["deviceId"];
5804
- if (typeof addonId !== "string" || typeof raw !== "string") continue;
5805
- const deviceId = Number(raw);
5806
- if (!Number.isInteger(deviceId) || deviceId <= 0) continue;
5807
- seen.set(`${addonId}:${deviceId}`, {
5808
- deviceId,
5809
- addonId
5810
- });
5811
- }
5812
- return [...seen.values()];
5813
- },
5814
- clear: async (deviceId) => {
5815
- const { deleted } = await store.deleteWhere.mutate({
5816
- collection: ADDON_DEVICE_SETTINGS_COLLECTION,
5817
- filter: { where: { deviceId: String(deviceId) } }
5818
- });
5819
- return deleted;
5820
- }
5943
+ list: () => listDeviceSettingsScopes(door),
5944
+ clear: (deviceId) => clearDeviceSettings(door, deviceId)
5821
5945
  };
5822
5946
  }
5823
5947
  //#endregion
@@ -6262,11 +6386,7 @@ function removalSteps(pctx, deviceId, providerAddonId, deletedAt) {
6262
6386
  run: async () => {
6263
6387
  const api = pctx.host.ctx.api?.settingsStore;
6264
6388
  if (api === void 0) throw new Error("settings-store api not available");
6265
- const { deleted } = await api.deleteWhere.mutate({
6266
- collection: "addon-device-settings",
6267
- filter: { where: { deviceId: String(deviceId) } }
6268
- });
6269
- return deleted;
6389
+ return clearDeviceSettings({ deleteWhere: (input) => api.deleteWhere.mutate(input) }, deviceId);
6270
6390
  }
6271
6391
  },
6272
6392
  {
@@ -8735,7 +8855,17 @@ var DeviceTombstoneStore = class {
8735
8855
  this.now = opts.now ?? (() => Date.now());
8736
8856
  this.retentionMs = opts.retentionMs ?? 7776e6;
8737
8857
  }
8738
- /** Lazy, idempotent declaration; a rejection is not latched. */
8858
+ /**
8859
+ * Declare the collection now. Idempotent; a rejection is not latched.
8860
+ *
8861
+ * Called at device-manager init (D871) so the table exists on a hub that has
8862
+ * not deleted a device yet. It used to be declared only by the first
8863
+ * `record` / `listSince`, i.e. by the first delete or by an implementer's
8864
+ * reconcile — so a hub whose implementers had not been redeployed, and where
8865
+ * nothing was deleted, never had the table, and the census read that as
8866
+ * "D865 is not running". A DECLARATION only: nothing is read, written or
8867
+ * purged here.
8868
+ */
8739
8869
  declare() {
8740
8870
  if (this.declared !== null) return this.declared;
8741
8871
  const run = this.backend.declareCollection({
@@ -10733,6 +10863,11 @@ var DeviceManagerAddon = class extends BaseAddon {
10733
10863
  backend: deviceRowBackendOf(settingsStoreApi),
10734
10864
  logger: this.ctx.logger.child("tombstones")
10735
10865
  });
10866
+ try {
10867
+ await tombstones.declare();
10868
+ } catch (err) {
10869
+ this.ctx.logger.warn("device tombstones collection not declared at init — retried on first use", { meta: { error: err instanceof Error ? err.message : String(err) } });
10870
+ }
10736
10871
  this.staleWrapperActivations.checkOnce(() => readBindingsStore(this.bindingsDeps));
10737
10872
  try {
10738
10873
  await purgeRetiredSettingsRows(deviceRows.retiredRowStore(), this.ctx.logger.child("RetiredRows"));
@@ -11067,4 +11202,4 @@ var DeviceManagerAddon = class extends BaseAddon {
11067
11202
  }
11068
11203
  };
11069
11204
  //#endregion
11070
- export { DeviceManagerAddon, DeviceManagerAddon as default, mergeAggregates, setWrapperActive as t };
11205
+ export { DeviceManagerAddon, DeviceManagerAddon as default, mergeAggregates, readDeviceOrThrow as n, setWrapperActive as r, createDeviceSettingsStore as t };
@@ -1,12 +1,3 @@
1
- /**
2
- * device-manager's side of `device-removal-hook` (D865): tell every implementer
3
- * a device was deleted, and answer the admin question "which stored data belongs
4
- * to devices that no longer exist?".
5
- *
6
- * Two entry points, one rule: **an implementer is told to delete only on a
7
- * recorded delete (a tombstone), or on an explicit operator confirm.** Nothing
8
- * here infers a deletion from a device being absent from a single read.
9
- */
10
1
  import { type CleanupDeletedDevicesResult, type DeviceDataEntry, type DeviceRemovedInput, type DeviceRemovedResult, type IScopedLogger, type OrphanDeviceData, type SettingsStoreClient } from "@camstack/types";
11
2
  import type { RemovalCleanup, RemovalStep } from "./removal-cleanup.js";
12
3
  /** The capability name implementers register under. */
@@ -97,7 +88,5 @@ export interface CleanupDeps {
97
88
  export declare function cleanupDeletedDevicesData(deps: CleanupDeps, input: {
98
89
  readonly confirm: boolean;
99
90
  }): Promise<CleanupDeletedDevicesResult>;
100
- /** The settings-store collection every addon's per-device settings share. */
101
- export declare const ADDON_DEVICE_SETTINGS_COLLECTION = "addon-device-settings";
102
91
  /** Scope access over the settings store; undefined when the store is unavailable. */
103
92
  export declare function settingsScopes(store: Pick<SettingsStoreClient, "query" | "deleteWhere"> | undefined): SettingsScopeAccess | undefined;
@@ -47,8 +47,18 @@ export declare class DeviceTombstoneStore {
47
47
  private readonly retentionMs;
48
48
  private declared;
49
49
  constructor(opts: DeviceTombstoneStoreOptions);
50
- /** Lazy, idempotent declaration; a rejection is not latched. */
51
- private declare;
50
+ /**
51
+ * Declare the collection now. Idempotent; a rejection is not latched.
52
+ *
53
+ * Called at device-manager init (D871) so the table exists on a hub that has
54
+ * not deleted a device yet. It used to be declared only by the first
55
+ * `record` / `listSince`, i.e. by the first delete or by an implementer's
56
+ * reconcile — so a hub whose implementers had not been redeployed, and where
57
+ * nothing was deleted, never had the table, and the census read that as
58
+ * "D865 is not running". A DECLARATION only: nothing is read, written or
59
+ * purged here.
60
+ */
61
+ declare(): Promise<void>;
52
62
  /** Record a deletion. Re-recording the same id keeps the EARLIER `deletedAt`. */
53
63
  record(tombstone: DeviceTombstone): Promise<void>;
54
64
  /** Tombstones with `deletedAt >= sinceMs`, oldest first. Expired ones are pruned first. */
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-GgG-7amw.js");
6
+ const require_dist = require("../../dist-BKhlcYz6.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { Or as BaseAddon, mn as logDestinationCapability } from "../../dist-Dc8GKC5H.mjs";
1
+ import { gn as logDestinationCapability, jr as BaseAddon } from "../../dist-9fcsrFU3.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-GgG-7amw.js");
7
- const require_device_ca = require("../../device-ca-BSvkXqyI.js");
8
- const require_constants = require("../../constants-wkcn5Ij3.js");
6
+ const require_dist = require("../../dist-BKhlcYz6.js");
7
+ const require_device_ca = require("../../device-ca-DNHjts4_.js");
8
+ const require_constants = require("../../constants-CRI3QzT4.js");
9
9
  const require_platform_key_source = require("../../platform-key-source-Di7HrlGR.js");
10
10
  let node_crypto = require("node:crypto");
11
11
  let _camstack_types_node = require("@camstack/types/node");
@@ -388,6 +388,8 @@ var NOT_INITIALIZED = {
388
388
  state: "locked",
389
389
  reason: "not-initialized"
390
390
  };
391
+ /** The only refs `importSecret` accepts: a camera's restream tokens (D870 migration). */
392
+ var IMPORTABLE_REF = /^secret:\/\/stream-broker\/device\/[0-9]+\/rtspTokens$/;
391
393
  var KeychainService = class {
392
394
  deps;
393
395
  unlock = NOT_INITIALIZED;
@@ -782,6 +784,17 @@ var KeychainService = class {
782
784
  const ref = SYSTEM_HELD_SECRET_REFS[name];
783
785
  return this.put(require_device_ca.SYSTEM_SECRET_OWNER, ref, value, `user:${userId}`);
784
786
  }
787
+ /**
788
+ * An operator tool stores a carried-over value at an addon's own ref (D870).
789
+ * Stored under the ref's owner, audited as the operator.
790
+ */
791
+ async importSecret(userId, ref, value) {
792
+ if (!IMPORTABLE_REF.test(ref)) throw new Error(`keychain: "${ref}" is not an importable ref (restream tokens only)`);
793
+ if ((await this.deps.repo.getSecrets([ref])).has(ref)) throw new Error(`keychain: a value is already stored at ${ref} - import refuses to overwrite`);
794
+ const parts = require_dist.parseSecretRef(ref);
795
+ if (parts === null) throw new Error(`keychain: "${ref}" is not a secret ref`);
796
+ return this.put(parts.owner, ref, value, `user:${userId}`);
797
+ }
785
798
  async listAudit(limit) {
786
799
  return this.deps.repo.listAudit(limit);
787
800
  }
@@ -1670,24 +1683,28 @@ async function blobsFor(door, owner, scope) {
1670
1683
  switch (scope.kind) {
1671
1684
  case "global":
1672
1685
  case "node": {
1673
- const forked = await door.get({
1686
+ const legacyBlob = await door.get({
1674
1687
  namespace: owner,
1675
1688
  collection: "addon-settings",
1676
1689
  key: "root"
1677
1690
  });
1678
- const inProcess = await prefixRows(door, "addon-settings", `${owner}.`);
1679
- if (inProcess === null) return null;
1680
- return [forked, ...inProcess];
1691
+ const rows = await prefixRows(door, "addon-settings", `${owner}.`);
1692
+ return rows === null ? null : [legacyBlob, ...rows];
1681
1693
  }
1682
1694
  case "device": {
1683
- const forked = await door.get({
1695
+ const legacyBlob = await door.get({
1684
1696
  namespace: owner,
1685
1697
  collection: "addon-devices",
1686
1698
  key: String(scope.deviceId)
1687
1699
  });
1688
- const doorRows = await prefixRows(door, "addon-device-settings", `device-manager:${scope.deviceId}.`);
1689
- if (doorRows === null) return null;
1690
- return [forked, ...doorRows];
1700
+ const own = await prefixRows(door, "addon-device-settings", `${owner}:${scope.deviceId}.`);
1701
+ const connection = owner === "device-manager" ? [] : await prefixRows(door, "addon-device-settings", `device-manager:${scope.deviceId}.`);
1702
+ if (own === null || connection === null) return null;
1703
+ return [
1704
+ legacyBlob,
1705
+ ...own,
1706
+ ...connection
1707
+ ];
1691
1708
  }
1692
1709
  case "integration": return (await door.query({
1693
1710
  collection: "integration_settings",
@@ -1861,6 +1878,7 @@ var KeychainAddon = class extends require_dist.BaseAddon {
1861
1878
  listAudit: (input) => service.listAudit(input.limit ?? 100),
1862
1879
  reveal: (input) => service.reveal(input.caller.userId, input.ref),
1863
1880
  setSystemSecret: (input) => service.setSystemSecret(input.caller.userId, input.name, input.value),
1881
+ importSecret: (input) => service.importSecret(input.caller.userId, input.ref, input.value),
1864
1882
  deleteOrphans: (input) => service.deleteOrphans(input.caller.userId, input.refs),
1865
1883
  rotateMasterKey: (input) => service.rotateMasterKey(input.caller.userId),
1866
1884
  purgeRetiredKeys: async (input) => ({ purged: await service.purgeRetiredKeys(input.caller.userId) }),
@@ -1,6 +1,6 @@
1
- import { L as KEYCHAIN_RESET_TRIGGER_ACTOR, Or as BaseAddon, Xr as formatSecretScope, ai as normalizeSecretOwner, ci as parseSecretRef, cn as keychainCapability, sn as keychainAdminCapability, yi as EventCategory } from "../../dist-Dc8GKC5H.mjs";
2
- import { d as JWT_SIGNING_KEY_REF, n as DEVICE_CA_KEY_REF, p as SYSTEM_SECRET_OWNER } from "../../device-ca-DvIZjXIl.mjs";
3
- import { a as MESH_CA_KEY_REF } from "../../constants-DQK705Sb.mjs";
1
+ import { $r as formatSecretScope, L as KEYCHAIN_RESET_TRIGGER_ACTOR, Si as EventCategory, ci as normalizeSecretOwner, di as parseSecretRef, jr as BaseAddon, ln as keychainAdminCapability, un as keychainCapability } from "../../dist-9fcsrFU3.mjs";
2
+ import { d as JWT_SIGNING_KEY_REF, n as DEVICE_CA_KEY_REF, p as SYSTEM_SECRET_OWNER } from "../../device-ca-DLKXYseS.mjs";
3
+ import { a as MESH_CA_KEY_REF } from "../../constants-CIzPjw7L.mjs";
4
4
  import { n as getPlatformKeychainKey } from "../../platform-key-source-BWlq0jjn.mjs";
5
5
  import { createCipheriv, createDecipheriv, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
6
6
  import { restrictDirToOwnerSync, restrictFileToOwnerSync, writeOwnerOnlyFileSync } from "@camstack/types/node";
@@ -382,6 +382,8 @@ var NOT_INITIALIZED = {
382
382
  state: "locked",
383
383
  reason: "not-initialized"
384
384
  };
385
+ /** The only refs `importSecret` accepts: a camera's restream tokens (D870 migration). */
386
+ var IMPORTABLE_REF = /^secret:\/\/stream-broker\/device\/[0-9]+\/rtspTokens$/;
385
387
  var KeychainService = class {
386
388
  deps;
387
389
  unlock = NOT_INITIALIZED;
@@ -776,6 +778,17 @@ var KeychainService = class {
776
778
  const ref = SYSTEM_HELD_SECRET_REFS[name];
777
779
  return this.put(SYSTEM_SECRET_OWNER, ref, value, `user:${userId}`);
778
780
  }
781
+ /**
782
+ * An operator tool stores a carried-over value at an addon's own ref (D870).
783
+ * Stored under the ref's owner, audited as the operator.
784
+ */
785
+ async importSecret(userId, ref, value) {
786
+ if (!IMPORTABLE_REF.test(ref)) throw new Error(`keychain: "${ref}" is not an importable ref (restream tokens only)`);
787
+ if ((await this.deps.repo.getSecrets([ref])).has(ref)) throw new Error(`keychain: a value is already stored at ${ref} - import refuses to overwrite`);
788
+ const parts = parseSecretRef(ref);
789
+ if (parts === null) throw new Error(`keychain: "${ref}" is not a secret ref`);
790
+ return this.put(parts.owner, ref, value, `user:${userId}`);
791
+ }
779
792
  async listAudit(limit) {
780
793
  return this.deps.repo.listAudit(limit);
781
794
  }
@@ -1664,24 +1677,28 @@ async function blobsFor(door, owner, scope) {
1664
1677
  switch (scope.kind) {
1665
1678
  case "global":
1666
1679
  case "node": {
1667
- const forked = await door.get({
1680
+ const legacyBlob = await door.get({
1668
1681
  namespace: owner,
1669
1682
  collection: "addon-settings",
1670
1683
  key: "root"
1671
1684
  });
1672
- const inProcess = await prefixRows(door, "addon-settings", `${owner}.`);
1673
- if (inProcess === null) return null;
1674
- return [forked, ...inProcess];
1685
+ const rows = await prefixRows(door, "addon-settings", `${owner}.`);
1686
+ return rows === null ? null : [legacyBlob, ...rows];
1675
1687
  }
1676
1688
  case "device": {
1677
- const forked = await door.get({
1689
+ const legacyBlob = await door.get({
1678
1690
  namespace: owner,
1679
1691
  collection: "addon-devices",
1680
1692
  key: String(scope.deviceId)
1681
1693
  });
1682
- const doorRows = await prefixRows(door, "addon-device-settings", `device-manager:${scope.deviceId}.`);
1683
- if (doorRows === null) return null;
1684
- return [forked, ...doorRows];
1694
+ const own = await prefixRows(door, "addon-device-settings", `${owner}:${scope.deviceId}.`);
1695
+ const connection = owner === "device-manager" ? [] : await prefixRows(door, "addon-device-settings", `device-manager:${scope.deviceId}.`);
1696
+ if (own === null || connection === null) return null;
1697
+ return [
1698
+ legacyBlob,
1699
+ ...own,
1700
+ ...connection
1701
+ ];
1685
1702
  }
1686
1703
  case "integration": return (await door.query({
1687
1704
  collection: "integration_settings",
@@ -1855,6 +1872,7 @@ var KeychainAddon = class extends BaseAddon {
1855
1872
  listAudit: (input) => service.listAudit(input.limit ?? 100),
1856
1873
  reveal: (input) => service.reveal(input.caller.userId, input.ref),
1857
1874
  setSystemSecret: (input) => service.setSystemSecret(input.caller.userId, input.name, input.value),
1875
+ importSecret: (input) => service.importSecret(input.caller.userId, input.ref, input.value),
1858
1876
  deleteOrphans: (input) => service.deleteOrphans(input.caller.userId, input.refs),
1859
1877
  rotateMasterKey: (input) => service.rotateMasterKey(input.caller.userId),
1860
1878
  purgeRetiredKeys: async (input) => ({ purged: await service.purgeRetiredKeys(input.caller.userId) }),
@@ -96,6 +96,14 @@ export declare class KeychainService {
96
96
  ref: string;
97
97
  version: number;
98
98
  }>;
99
+ /**
100
+ * An operator tool stores a carried-over value at an addon's own ref (D870).
101
+ * Stored under the ref's owner, audited as the operator.
102
+ */
103
+ importSecret(userId: string, ref: string, value: string): Promise<{
104
+ ref: string;
105
+ version: number;
106
+ }>;
99
107
  listAudit(limit: number): Promise<readonly KeychainAuditEntry[]>;
100
108
  reveal(userId: string, ref: string): Promise<{
101
109
  value: string;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-GgG-7amw.js");
3
+ const require_dist = require("../../dist-BKhlcYz6.js");
4
4
  //#region src/builtins/liveness-monitor/liveness-checks.ts
5
5
  var NO_DEVICES = "liveness:no-devices";
6
6
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -1,4 +1,4 @@
1
- import { Dr as errMsg, G as RecordingStatusSchema, Or as BaseAddon, W as RECORDING_SOURCE_CAMSTACK_ADDON, Wr as createEvent, yi as EventCategory } from "../../dist-Dc8GKC5H.mjs";
1
+ import { Ar as errMsg, G as RecordingStatusSchema, Si as EventCategory, W as RECORDING_SOURCE_CAMSTACK_ADDON, jr as BaseAddon, qr as createEvent } from "../../dist-9fcsrFU3.mjs";
2
2
  //#region src/builtins/liveness-monitor/liveness-checks.ts
3
3
  var NO_DEVICES = "liveness:no-devices";
4
4
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -3,10 +3,10 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-GgG-7amw.js");
6
+ const require_dist = require("../../dist-BKhlcYz6.js");
7
7
  const require_safe_buffer$1 = require("../../safe-buffer-D3aoa-7X.js");
8
8
  const require_ms$1 = require("../../ms-LB3giGoU.js");
9
- const require_device_ca = require("../../device-ca-BSvkXqyI.js");
9
+ const require_device_ca = require("../../device-ca-DNHjts4_.js");
10
10
  let node_crypto = require("node:crypto");
11
11
  node_crypto = require_chunk.__toESM(node_crypto);
12
12
  let crypto$1 = require("crypto");
@@ -1,8 +1,8 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { E as DEVICE_NONCE_TTL_MS, J as ScopedTokenSchema, Or as BaseAddon, Pt as deviceCredentialsCapability, T as DEVICE_ENROLLMENT_TTL_MS, X as SsoBridgeClaimsSchema, Yt as formatDeviceRevoker, a as ApiKeyRecordSchema, ar as userManagementCapability, dt as buildDeviceEnrollmentLink, ft as buildDeviceSignatureMessage, ot as authProviderCapability, tt as UserRecordSchema, vi as userError } from "../../dist-Dc8GKC5H.mjs";
2
+ import { E as DEVICE_NONCE_TTL_MS, It as deviceCredentialsCapability, Q as SsoBridgeClaimsSchema, T as DEVICE_ENROLLMENT_TTL_MS, X as ScopedTokenSchema, Zt as formatDeviceRevoker, a as ApiKeyRecordSchema, cr as userManagementCapability, ct as authProviderCapability, jr as BaseAddon, mt as buildDeviceSignatureMessage, pt as buildDeviceEnrollmentLink, rt as UserRecordSchema, xi as userError } from "../../dist-9fcsrFU3.mjs";
3
3
  import { t as require_safe_buffer } from "../../safe-buffer-B1OjL1I9.mjs";
4
4
  import { t as require_ms } from "../../ms-CgH2OFlD.mjs";
5
- import { _ as setProcessJwtSigningKey, a as importDevicePublicKey, c as rebuildDeviceCaCertificate, d as JWT_SIGNING_KEY_REF, g as processJwtSigningKey, h as loadJwtSigningKey, i as generateDeviceCa, l as verifyDeviceLeaf, m as getProcessJwtSigningKeyState, n as DEVICE_CA_KEY_REF, o as issueDeviceLeaf, r as DEVICE_CA_SETTINGS_SECTION, s as loadDeviceCa, t as DEVICE_CA_FIELD, u as verifyDeviceSignature } from "../../device-ca-DvIZjXIl.mjs";
5
+ import { _ as setProcessJwtSigningKey, a as importDevicePublicKey, c as rebuildDeviceCaCertificate, d as JWT_SIGNING_KEY_REF, g as processJwtSigningKey, h as loadJwtSigningKey, i as generateDeviceCa, l as verifyDeviceLeaf, m as getProcessJwtSigningKeyState, n as DEVICE_CA_KEY_REF, o as issueDeviceLeaf, r as DEVICE_CA_SETTINGS_SECTION, s as loadDeviceCa, t as DEVICE_CA_FIELD, u as verifyDeviceSignature } from "../../device-ca-DLKXYseS.mjs";
6
6
  import * as crypto$1 from "node:crypto";
7
7
  import { X509Certificate, createHash, randomUUID, timingSafeEqual } from "node:crypto";
8
8
  import nodeCrypto from "crypto";
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-GgG-7amw.js");
4
- const require_hub_mdns_ciao = require("../../hub-mdns-ciao-CBLvq2oj.js");
3
+ const require_dist = require("../../dist-BKhlcYz6.js");
4
+ const require_hub_mdns_ciao = require("../../hub-mdns-ciao-3Zc9G9MS.js");
5
5
  let zod = require("zod");
6
6
  let node_net = require("node:net");
7
7
  let node_os = require("node:os");
@@ -900,6 +900,11 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
900
900
  this.putCertificateOnListener("upload");
901
901
  return this.snapshotTls();
902
902
  },
903
+ useStoredUploadedCertificate: async () => {
904
+ await require_hub_mdns_ciao.useStoredUploadedCertificate(this.tlsDataDir());
905
+ this.putCertificateOnListener("upload");
906
+ return this.snapshotTls();
907
+ },
903
908
  downloadCa: async () => {
904
909
  return { pem: this.snapshotTls().caCertPem ?? "" };
905
910
  },
@@ -1,5 +1,5 @@
1
- import { $t as isAppLinkBase, F as HUB_MDNS_SERVICE_TYPE, Fn as resolveAppConnections, Hn as resolveNotificationTapAddress, I as HUB_MDNS_TXT_KEYS, On as pickAppLinkHub, Or as BaseAddon, U as NetworkTunnelStartedDataSchema, _t as checkRoleAddress, fn as localNetworkCapability, l as CAMSTACK_APP_LINK_ORIGIN, nn as isDefaultAppConnectionEndpoint, sr as validateCustomAddress, yi as EventCategory, zn as resolveHubAddressRoles } from "../../dist-Dc8GKC5H.mjs";
2
- import { C as DEFAULT_LAN_HTTP_PORT, O as readLanHttpState, T as applyLanHttp, a as storeUploadedCertificate, b as ensureTlsCert, d as servedHttpsLeafFingerprint, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, m as readExtraSans, n as applyCertificateToListener, r as regenerateCertificate, t as createCiaoPublisher, v as writeExtraSans } from "../../hub-mdns-ciao-DMlQTdPU.mjs";
1
+ import { An as pickAppLinkHub, F as HUB_MDNS_SERVICE_TYPE, I as HUB_MDNS_TXT_KEYS, Ln as resolveAppConnections, Si as EventCategory, U as NetworkTunnelStartedDataSchema, Vn as resolveHubAddressRoles, Wn as resolveNotificationTapAddress, in as isDefaultAppConnectionEndpoint, jr as BaseAddon, l as CAMSTACK_APP_LINK_ORIGIN, mn as localNetworkCapability, tn as isAppLinkBase, ur as validateCustomAddress, yt as checkRoleAddress } from "../../dist-9fcsrFU3.mjs";
2
+ import { P as readLanHttpState, a as storeUploadedCertificate, d as servedHttpsLeafFingerprint, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, j as applyLanHttp, k as DEFAULT_LAN_HTTP_PORT, m as readExtraSans, n as applyCertificateToListener, o as useStoredUploadedCertificate, r as regenerateCertificate, t as createCiaoPublisher, v as writeExtraSans, w as ensureTlsCert } from "../../hub-mdns-ciao-Dy2YjRqC.mjs";
3
3
  import { z } from "zod";
4
4
  import { isIP } from "node:net";
5
5
  import * as os$1 from "node:os";
@@ -897,6 +897,11 @@ var LocalNetworkAddon = class extends BaseAddon {
897
897
  this.putCertificateOnListener("upload");
898
898
  return this.snapshotTls();
899
899
  },
900
+ useStoredUploadedCertificate: async () => {
901
+ await useStoredUploadedCertificate(this.tlsDataDir());
902
+ this.putCertificateOnListener("upload");
903
+ return this.snapshotTls();
904
+ },
900
905
  downloadCa: async () => {
901
906
  return { pem: this.snapshotTls().caCertPem ?? "" };
902
907
  },