@camstack/system 1.2.444 → 1.2.445

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 (142) hide show
  1. package/dist/addon-runner.js +40 -31
  2. package/dist/addon-runner.mjs +41 -32
  3. package/dist/{agent-https-DlpTMDqA.js → agent-https-CiOW0-sj.js} +810 -12
  4. package/dist/{agent-https-U0d4uvn2.mjs → agent-https-D4Q8iFNd.mjs} +697 -13
  5. package/dist/auth/admin-token-manager.d.ts +9 -3
  6. package/dist/auth/api-key-manager.d.ts +9 -3
  7. package/dist/auth/auth-audit-log.d.ts +9 -3
  8. package/dist/auth/device-credential-manager.d.ts +5 -1
  9. package/dist/auth/external-identity-manager.d.ts +8 -21
  10. package/dist/auth/login-session-manager.d.ts +11 -3
  11. package/dist/auth/scoped-token-manager.d.ts +8 -52
  12. package/dist/auth/totp-manager.d.ts +11 -3
  13. package/dist/auth/user-manager.d.ts +10 -17
  14. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  15. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  16. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  17. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  18. package/dist/builtins/alerts/alert-store.d.ts +32 -0
  19. package/dist/builtins/alerts/alerts.addon.d.ts +9 -2
  20. package/dist/builtins/alerts/alerts.addon.js +289 -150
  21. package/dist/builtins/alerts/alerts.addon.mjs +288 -150
  22. package/dist/builtins/alerts/record-kinds.d.ts +15 -0
  23. package/dist/builtins/autotrack/index.js +1 -1
  24. package/dist/builtins/autotrack/index.mjs +1 -1
  25. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -0
  26. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +134 -193
  27. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +134 -193
  28. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +4 -2
  29. package/dist/builtins/backup-orchestrator/encryption-key-store.d.ts +4 -2
  30. package/dist/builtins/backup-orchestrator/record-kinds.d.ts +58 -0
  31. package/dist/builtins/backup-orchestrator/schedule-store.d.ts +4 -2
  32. package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +4 -2
  33. package/dist/builtins/calendars/calendar-prefs-store.d.ts +13 -5
  34. package/dist/builtins/calendars/calendars.addon.d.ts +2 -2
  35. package/dist/builtins/calendars/calendars.addon.js +67 -64
  36. package/dist/builtins/calendars/calendars.addon.mjs +59 -64
  37. package/dist/builtins/calendars/record-kinds.d.ts +18 -0
  38. package/dist/builtins/camera-grid/index.js +1 -1
  39. package/dist/builtins/camera-grid/index.mjs +1 -1
  40. package/dist/builtins/cluster-agent/record-kinds.d.ts +36 -0
  41. package/dist/builtins/composer/composer.addon.js +2 -2
  42. package/dist/builtins/composer/composer.addon.mjs +2 -2
  43. package/dist/builtins/console-logging/index.js +1 -1
  44. package/dist/builtins/console-logging/index.mjs +1 -1
  45. package/dist/builtins/core-blocks/block-settings-store.d.ts +8 -4
  46. package/dist/builtins/core-blocks/core-block-store.d.ts +8 -16
  47. package/dist/builtins/core-blocks/core-blocks.addon.js +85 -112
  48. package/dist/builtins/core-blocks/core-blocks.addon.mjs +86 -113
  49. package/dist/builtins/core-blocks/index.mjs +1 -1
  50. package/dist/builtins/core-blocks/record-kinds.d.ts +26 -0
  51. package/dist/builtins/device-manager/device-manager.addon.js +111 -187
  52. package/dist/builtins/device-manager/device-manager.addon.mjs +110 -187
  53. package/dist/builtins/device-manager/device-tombstone-store.d.ts +9 -48
  54. package/dist/builtins/device-manager/record-kinds.d.ts +14 -0
  55. package/dist/builtins/hub-forwarder/index.js +1 -1
  56. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  57. package/dist/builtins/keychain/index.js +152 -22
  58. package/dist/builtins/keychain/index.mjs +152 -22
  59. package/dist/builtins/keychain/keychain-service.d.ts +3 -2
  60. package/dist/builtins/keychain/keychain-store.d.ts +13 -2
  61. package/dist/builtins/keychain/record-kinds.d.ts +16 -0
  62. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  63. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  64. package/dist/builtins/local-auth/auth-schema.d.ts +3 -1
  65. package/dist/builtins/local-auth/local-auth.addon.js +2903 -2123
  66. package/dist/builtins/local-auth/local-auth.addon.mjs +2904 -2124
  67. package/dist/builtins/local-auth/oauth-session-manager.d.ts +8 -48
  68. package/dist/builtins/local-auth/record-kinds.d.ts +141 -0
  69. package/dist/builtins/local-network/local-network.addon.js +2 -2
  70. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  71. package/dist/builtins/loki-logging/index.js +1 -1
  72. package/dist/builtins/loki-logging/index.mjs +1 -1
  73. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  74. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  75. package/dist/builtins/platform-probe/index.js +1 -1
  76. package/dist/builtins/platform-probe/index.mjs +1 -1
  77. package/dist/builtins/record-entries/index.js +1 -1
  78. package/dist/builtins/record-entries/index.mjs +1 -1
  79. package/dist/builtins/records/legacy-table-row-count.d.ts +5 -0
  80. package/dist/builtins/records/phase6-declare-gate.d.ts +28 -0
  81. package/dist/builtins/records-isolated.d.ts +10 -0
  82. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  83. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  84. package/dist/builtins/snapshot/index.js +1 -1
  85. package/dist/builtins/snapshot/index.mjs +1 -1
  86. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  87. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  88. package/dist/builtins/sqlite-storage/index.js +1 -1
  89. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  90. package/dist/builtins/sqlite-storage/integration-record-kinds.d.ts +30 -0
  91. package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -16
  92. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +5 -0
  93. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +6 -0
  94. package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +5 -0
  95. package/dist/builtins/sqlite-storage/records/records-engine.d.ts +4 -0
  96. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +5 -1
  97. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +17 -0
  98. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +111 -3
  99. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +111 -3
  100. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +9 -1
  101. package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +5 -2
  102. package/dist/builtins/storage-orchestrator/location-store.d.ts +7 -2
  103. package/dist/builtins/storage-orchestrator/record-kinds.d.ts +38 -0
  104. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -0
  105. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +196 -5
  106. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +195 -6
  107. package/dist/builtins/system-config/record-kinds.d.ts +32 -0
  108. package/dist/builtins/system-config/system-config.addon.js +53 -618
  109. package/dist/builtins/system-config/system-config.addon.mjs +29 -577
  110. package/dist/builtins/winston-logging/index.js +1 -1
  111. package/dist/builtins/winston-logging/index.mjs +1 -1
  112. package/dist/{composition-sources-C3rKncIF.mjs → composition-sources-BMt5cFYb.mjs} +1 -1
  113. package/dist/{composition-sources-NAPZddic.js → composition-sources-D3fi9Xns.js} +1 -1
  114. package/dist/{constants-BKX2QnIg.mjs → constants-BMHCxRzb.mjs} +1 -1
  115. package/dist/{constants-BXiNEIeV.js → constants-Br879Axi.js} +1 -1
  116. package/dist/{device-ca-DT9X2S6d.js → device-ca-CnJ_va7i.js} +1 -1
  117. package/dist/{device-ca-jxjSL8Ov.mjs → device-ca-T8osSMos.mjs} +1 -1
  118. package/dist/{dist-DERK-gP5.mjs → dist-BNunRyXT.mjs} +174 -58
  119. package/dist/{dist-D1vECb_6.js → dist-DgOG8flk.js} +233 -57
  120. package/dist/file-host-worker.js +1 -1
  121. package/dist/file-host-worker.mjs +1 -1
  122. package/dist/{hub-mdns-ciao-Cah9GCIg.js → hub-mdns-ciao-BIkTHq-n.js} +2 -2
  123. package/dist/{hub-mdns-ciao-CRaC97V0.mjs → hub-mdns-ciao-D16oRQ9K.mjs} +2 -2
  124. package/dist/index.d.ts +7 -0
  125. package/dist/index.js +3093 -2820
  126. package/dist/index.mjs +3065 -2809
  127. package/dist/kernel/index.d.ts +2 -0
  128. package/dist/kernel/moleculer/event-bus.d.ts +3 -1
  129. package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +5 -1
  130. package/dist/kernel/moleculer/remote-logger.d.ts +2 -2
  131. package/dist/kernel/transport/cap-route-resolver.d.ts +9 -38
  132. package/dist/phase6-declare-gate-Ci1-8uUn.js +98 -0
  133. package/dist/phase6-declare-gate-tkKOEitw.mjs +93 -0
  134. package/dist/read-all-rows-CVoO1ONM.js +29 -0
  135. package/dist/read-all-rows-TaPqdWNF.mjs +25 -0
  136. package/dist/records/read-all-rows.d.ts +6 -0
  137. package/dist/{restore-archive-daKyE24F.mjs → restore-archive-DR9MtO7J.mjs} +339 -9
  138. package/dist/{restore-archive-Dy-qKTdF.js → restore-archive-DjJnCgap.js} +353 -5
  139. package/dist/tls/agent-https-names.d.ts +9 -13
  140. package/dist/{wal-maintenance-dAv4IdzC.js → wal-maintenance-CODGqhKY.js} +0 -0
  141. package/dist/{wal-maintenance-zRc24mOC.mjs → wal-maintenance-CfvgtQ7C.mjs} +0 -0
  142. package/package.json +1 -1
@@ -1,4 +1,6 @@
1
- import { $i as EventCategory, Fr as BaseAddon, Pr as errMsg, ct as alertsCapability, i as AlertSchema, yi as createEvent } from "../../dist-DERK-gP5.mjs";
1
+ import { Ci as createEvent, Di as defineRecordKinds, Lr as errMsg, Rr as BaseAddon, ft as alertsCapability, i as AlertSchema, la as EventCategory } from "../../dist-BNunRyXT.mjs";
2
+ import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
3
+ import { t as resolvePhase6UseRecordsPathForHub } from "../../phase6-declare-gate-tkKOEitw.mjs";
2
4
  //#region src/builtins/alerts/critical-push.ts
3
5
  /** Alert categories that are critical system findings. */
4
6
  var CRITICAL_CATEGORIES = new Set([
@@ -277,6 +279,210 @@ function runnerPushLine(record) {
277
279
  return record.state === "refused" ? `${where}: refused to start. ${record.remedy ?? "See the Addons page."}` : `${where}: stopped after repeated crashes. Restart it from the Addons page.`;
278
280
  }
279
281
  //#endregion
282
+ //#region src/builtins/alerts/record-kinds.ts
283
+ var import_read_all_rows = require_read_all_rows();
284
+ /**
285
+ * Record kinds owned by alert-center (records plan phase 4).
286
+ */
287
+ /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
288
+ var ALERTS_COLLECTION = "alerts";
289
+ var _alertCenterRecordKinds = defineRecordKinds({ alerts: {
290
+ schema: AlertSchema.omit({ id: true }),
291
+ class: "audit",
292
+ writeTrigger: "EventBus categories the alert center tracks, operator mark read/dismiss, and model-download progress merges",
293
+ device: "none",
294
+ at: "none",
295
+ indexes: [
296
+ {
297
+ name: "read",
298
+ fields: ["read"]
299
+ },
300
+ {
301
+ name: "created_at",
302
+ fields: ["createdAt"]
303
+ },
304
+ {
305
+ name: "updated_at",
306
+ fields: ["updatedAt"]
307
+ }
308
+ ],
309
+ retention: {
310
+ owner: "alert-center",
311
+ reason: "maxAlerts cap and retentionDays enforced on write (enforceMaxAlerts / enforceRetention); read alerts preferred when trimming overflow"
312
+ },
313
+ adoptsFrom: ALERTS_COLLECTION
314
+ } });
315
+ var alertCenterRecordKinds = _alertCenterRecordKinds;
316
+ /** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
317
+ var alertsRecordKind = _alertCenterRecordKinds.alerts;
318
+ //#endregion
319
+ //#region src/builtins/alerts/alert-store.ts
320
+ function toRecord(row) {
321
+ return {
322
+ id: row.id,
323
+ data: row.data
324
+ };
325
+ }
326
+ function toRecordFromLegacy(row) {
327
+ return {
328
+ id: row.id,
329
+ data: row.data
330
+ };
331
+ }
332
+ function isRecord(value) {
333
+ return typeof value === "object" && value !== null && !Array.isArray(value);
334
+ }
335
+ function legacyGetData(value) {
336
+ if (!isRecord(value)) return null;
337
+ if ("data" in value) {
338
+ const data = value.data;
339
+ return isRecord(data) ? data : null;
340
+ }
341
+ return value;
342
+ }
343
+ var AlertStore = class AlertStore {
344
+ kind;
345
+ legacyStore;
346
+ constructor(kind, legacyStore) {
347
+ this.kind = kind;
348
+ this.legacyStore = legacyStore;
349
+ }
350
+ static of(records) {
351
+ return new AlertStore(records.kind(alertsRecordKind), null);
352
+ }
353
+ static legacy(store) {
354
+ return new AlertStore(null, store);
355
+ }
356
+ async legacyRows() {
357
+ const store = this.legacyStore;
358
+ if (store === null) return [];
359
+ return (await store.query.query({
360
+ collection: ALERTS_COLLECTION,
361
+ filter: {}
362
+ })).map((row) => toRecordFromLegacy({
363
+ id: row.id,
364
+ data: row.data
365
+ }));
366
+ }
367
+ async list(filter) {
368
+ let out;
369
+ const kind = this.kind;
370
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
371
+ else out = [...await this.legacyRows()];
372
+ if (filter?.unreadOnly === true) out = out.filter((r) => r.data["read"] === false);
373
+ out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
374
+ const limit = filter?.limit ?? 100;
375
+ return out.slice(0, limit);
376
+ }
377
+ async countUnread() {
378
+ return (await this.list({
379
+ unreadOnly: true,
380
+ limit: 1e4
381
+ })).length;
382
+ }
383
+ async countAll() {
384
+ const kind = this.kind;
385
+ if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).length;
386
+ return (await this.legacyRows()).length;
387
+ }
388
+ async getData(id) {
389
+ const kind = this.kind;
390
+ if (kind !== null) {
391
+ const row = await kind.get(id);
392
+ if (row === null) return null;
393
+ return row.data;
394
+ }
395
+ const store = this.legacyStore;
396
+ if (store === null) return null;
397
+ return legacyGetData(await store.get.query({
398
+ collection: ALERTS_COLLECTION,
399
+ key: id
400
+ }));
401
+ }
402
+ async mergeUpdate(id, patch) {
403
+ const existing = await this.getData(id);
404
+ if (existing === null) return;
405
+ await this.putRaw(id, {
406
+ ...existing,
407
+ ...patch
408
+ });
409
+ }
410
+ async persist(alert) {
411
+ const { id, ...body } = alert;
412
+ const data = alertsRecordKind.schema.parse(body);
413
+ const kind = this.kind;
414
+ if (kind !== null) {
415
+ await kind.put({
416
+ id,
417
+ data
418
+ });
419
+ return;
420
+ }
421
+ await this.putRaw(id, {
422
+ ...body,
423
+ id
424
+ });
425
+ }
426
+ async putRaw(id, data) {
427
+ const { id: _drop, ...body } = AlertSchema.parse({
428
+ id,
429
+ ...data
430
+ });
431
+ const kind = this.kind;
432
+ if (kind !== null) {
433
+ await kind.put({
434
+ id,
435
+ data: body
436
+ });
437
+ return;
438
+ }
439
+ const store = this.legacyStore;
440
+ if (store === null) return;
441
+ await store.set.mutate({
442
+ collection: ALERTS_COLLECTION,
443
+ key: id,
444
+ value: {
445
+ id,
446
+ ...body
447
+ }
448
+ });
449
+ }
450
+ async delete(id) {
451
+ const kind = this.kind;
452
+ if (kind !== null) {
453
+ await kind.delete(id);
454
+ return;
455
+ }
456
+ const store = this.legacyStore;
457
+ if (store === null) return;
458
+ await store.delete.mutate({
459
+ collection: ALERTS_COLLECTION,
460
+ key: id
461
+ });
462
+ }
463
+ async listAllByCreatedAtAsc() {
464
+ const kind = this.kind;
465
+ let out;
466
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind)).map(toRecord);
467
+ else out = [...await this.legacyRows()];
468
+ out.sort((a, b) => Number(a.data["createdAt"] ?? 0) - Number(b.data["createdAt"] ?? 0));
469
+ return out;
470
+ }
471
+ async listRecent(limit) {
472
+ const kind = this.kind;
473
+ let out;
474
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
475
+ else out = [...await this.legacyRows()];
476
+ out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
477
+ return out.slice(0, limit);
478
+ }
479
+ async findWhereDataField(field, value) {
480
+ const kind = this.kind;
481
+ if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).filter((r) => r.data[field] === value).map(toRecord);
482
+ return (await this.legacyRows()).filter((r) => r.data[field] === value);
483
+ }
484
+ };
485
+ //#endregion
280
486
  //#region src/builtins/alerts/alerts.addon.ts
281
487
  var CATEGORY_MAPPINGS = {
282
488
  "addon.crashed": {
@@ -449,13 +655,18 @@ var DEFAULT_CONFIG = {
449
655
  maxAlerts: 500,
450
656
  retentionDays: 30,
451
657
  criticalPushEnabled: true,
452
- criticalPushTargetIds: ""
658
+ criticalPushTargetIds: []
453
659
  };
660
+ /** Accept the live `string[]` shape and the pre-multiselect CSV string. */
661
+ function normalizeCriticalPushTargetIds(raw) {
662
+ if (Array.isArray(raw)) return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim());
663
+ if (typeof raw === "string" && raw.trim().length > 0) return raw.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
664
+ return [];
665
+ }
454
666
  /** One burst of critical findings (a whole boot of refused runners) is ONE digest push. */
455
667
  var PUSH_COALESCE_MS = 2e3;
456
668
  /** Addons whose (re)start is a reason to retry pending critical pushes. */
457
669
  var PUSH_RECONCILE_ADDONS = new Set(["notifiers", "notification-center"]);
458
- var ALERTS_COLLECTION = "alerts";
459
670
  var EVENT_SOURCE = {
460
671
  type: "addon",
461
672
  id: "alert-center"
@@ -476,6 +687,7 @@ function toPrunable(record) {
476
687
  };
477
688
  }
478
689
  var AlertCenterAddon = class extends BaseAddon {
690
+ alertStore = null;
479
691
  unsubscribers = [];
480
692
  /** How long a burst of critical findings is gathered into one digest push. */
481
693
  pushCoalesceMs;
@@ -490,6 +702,11 @@ var AlertCenterAddon = class extends BaseAddon {
490
702
  */
491
703
  rateLimitCounters = /* @__PURE__ */ new Map();
492
704
  async onInitialize() {
705
+ const records = this.ctx.records;
706
+ const store = this.ctx.api?.settingsStore;
707
+ const useRecords = records !== void 0 && store !== void 0 && await resolvePhase6UseRecordsPathForHub(this.ctx, "alert-center", alertCenterRecordKinds, ["alerts"]);
708
+ this.alertStore = useRecords && records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
709
+ if (this.alertStore === null) throw new Error("alert-center needs ctx.records or settings-store on the hub");
493
710
  const alertsProvider = {
494
711
  emit: (alert) => this.emitAlert(alert),
495
712
  update: (input) => this.updateAlert(input.alertId, input.patch),
@@ -509,6 +726,7 @@ var AlertCenterAddon = class extends BaseAddon {
509
726
  this.unsubscribers = unsubs;
510
727
  this.reconcilePendingPushes();
511
728
  this.dismissLegacyStreamCards(void 0);
729
+ this.migrateCriticalPushTargetIds();
512
730
  this.ctx.logger.info("Initialized", { meta: { trackedCategoriesCount: TRACKED_CATEGORIES.length } });
513
731
  return [{
514
732
  capability: alertsCapability,
@@ -556,43 +774,28 @@ var AlertCenterAddon = class extends BaseAddon {
556
774
  type: "boolean",
557
775
  key: "criticalPushEnabled",
558
776
  label: "Push critical system alerts",
559
- description: "A runner that failed or refused to start, or a node whose runners are degraded, is pushed straight to the notifier targets - even when notification-center is down.",
777
+ description: "A runner that failed or refused to start, or a node whose runners are degraded, is pushed straight to the notifier targets — even when Notification Center is down. This path does not use notification rules.",
560
778
  default: true
561
779
  }),
562
780
  this.field({
563
- type: "text",
781
+ type: "notification-target-multiselect",
564
782
  key: "criticalPushTargetIds",
565
783
  label: "Critical push targets",
566
- description: "Comma-separated notifier target ids. Empty = every enabled shared (not personal) target.",
567
- default: ""
784
+ description: "Notifier targets that receive critical system alerts. Empty = every enabled shared (not personal) target.",
785
+ default: []
568
786
  })
569
787
  ]
570
788
  }] });
571
789
  }
572
790
  async listAlerts(filter) {
573
- const backend = this.ctx.api.settingsStore;
574
- if (!backend) return [];
575
- const whereClause = {};
576
- if (filter?.unreadOnly) whereClause.read = false;
577
- return (await backend.query.query({
578
- collection: ALERTS_COLLECTION,
579
- filter: {
580
- where: Object.keys(whereClause).length > 0 ? whereClause : void 0,
581
- orderBy: {
582
- field: "updatedAt",
583
- direction: "desc"
584
- },
585
- limit: filter?.limit ?? 100
586
- }
587
- })).map(parseAlert);
791
+ const store = this.alertStore;
792
+ if (store === null) return [];
793
+ return (await store.list(filter)).map(parseAlert);
588
794
  }
589
795
  async getUnreadCount() {
590
- const backend = this.ctx.api.settingsStore;
591
- if (!backend) return 0;
592
- return backend.count.query({
593
- collection: ALERTS_COLLECTION,
594
- filter: { where: { read: false } }
595
- });
796
+ const store = this.alertStore;
797
+ if (store === null) return 0;
798
+ return store.countUnread();
596
799
  }
597
800
  async markRead(alertId) {
598
801
  await this.mergeUpdate(alertId, {
@@ -601,11 +804,11 @@ var AlertCenterAddon = class extends BaseAddon {
601
804
  });
602
805
  }
603
806
  async markAllRead() {
604
- const backend = this.ctx.api.settingsStore;
605
- if (!backend) return;
606
- const unread = await backend.query.query({
607
- collection: ALERTS_COLLECTION,
608
- filter: { where: { read: false } }
807
+ const store = this.alertStore;
808
+ if (store === null) return;
809
+ const unread = await store.list({
810
+ unreadOnly: true,
811
+ limit: 1e4
609
812
  });
610
813
  const now = Date.now();
611
814
  for (const record of unread) await this.mergeUpdate(record.id, {
@@ -702,14 +905,14 @@ var AlertCenterAddon = class extends BaseAddon {
702
905
  }
703
906
  }
704
907
  async readRunnerRecord(alertId) {
705
- const backend = this.ctx.api.settingsStore;
706
- if (!backend) return null;
707
- const raw = await backend.get.query({
708
- collection: ALERTS_COLLECTION,
709
- key: alertId
908
+ const store = this.alertStore;
909
+ if (store === null) return null;
910
+ const raw = await store.getData(alertId);
911
+ if (raw === null) return null;
912
+ const alert = AlertSchema.safeParse({
913
+ id: alertId,
914
+ ...raw
710
915
  });
711
- if (raw === null || raw === void 0 || typeof raw !== "object") return null;
712
- const alert = AlertSchema.safeParse(raw);
713
916
  if (!alert.success || alert.data.status === "dismissed") return null;
714
917
  return parseRunnerRecord(alert.data.metadata?.["runner"]);
715
918
  }
@@ -837,13 +1040,10 @@ var AlertCenterAddon = class extends BaseAddon {
837
1040
  });
838
1041
  }
839
1042
  async readAlertRaw(alertId) {
840
- const backend = this.ctx.api.settingsStore;
841
- if (!backend) return null;
842
- const raw = await backend.get.query({
843
- collection: ALERTS_COLLECTION,
844
- key: alertId
845
- });
846
- if (raw === null || raw === void 0 || typeof raw !== "object") return null;
1043
+ const store = this.alertStore;
1044
+ if (store === null) return null;
1045
+ const raw = await store.getData(alertId);
1046
+ if (raw === null) return null;
847
1047
  const rec = Object.fromEntries(Object.entries(raw));
848
1048
  const meta = rec["metadata"];
849
1049
  const push = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta["push"] : void 0;
@@ -861,9 +1061,19 @@ var AlertCenterAddon = class extends BaseAddon {
861
1061
  pushPolicy() {
862
1062
  return {
863
1063
  enabled: this.config.criticalPushEnabled,
864
- targetIds: this.config.criticalPushTargetIds.split(",").map((id) => id.trim()).filter((id) => id.length > 0)
1064
+ targetIds: normalizeCriticalPushTargetIds(this.config.criticalPushTargetIds)
865
1065
  };
866
1066
  }
1067
+ /** Rewrite a legacy CSV `criticalPushTargetIds` string into `string[]`. */
1068
+ async migrateCriticalPushTargetIds() {
1069
+ const raw = this.config.criticalPushTargetIds;
1070
+ if (typeof raw !== "string") return;
1071
+ try {
1072
+ await this.updateGlobalSettings({ criticalPushTargetIds: normalizeCriticalPushTargetIds(raw) });
1073
+ } catch (err) {
1074
+ this.ctx.logger.warn("criticalPushTargetIds CSV migration failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
1075
+ }
1076
+ }
867
1077
  pushPorts() {
868
1078
  const api = this.ctx.api;
869
1079
  return {
@@ -940,27 +1150,16 @@ var AlertCenterAddon = class extends BaseAddon {
940
1150
  return this.pushChain;
941
1151
  }
942
1152
  async storePushState(alertId, push) {
943
- const backend = this.ctx.api.settingsStore;
944
- if (!backend) return;
945
- const raw = await backend.get.query({
946
- collection: ALERTS_COLLECTION,
947
- key: alertId
948
- });
949
- if (raw === null || raw === void 0 || typeof raw !== "object") return;
950
- const existing = Object.fromEntries(Object.entries(raw));
951
- const meta = existing["metadata"];
1153
+ const store = this.alertStore;
1154
+ if (store === null) return;
1155
+ const raw = await store.getData(alertId);
1156
+ if (raw === null) return;
1157
+ const meta = raw["metadata"];
952
1158
  const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : {};
953
- await backend.set.mutate({
954
- collection: ALERTS_COLLECTION,
955
- key: alertId,
956
- value: {
957
- ...existing,
958
- metadata: {
959
- ...metadata,
960
- push
961
- }
962
- }
963
- });
1159
+ await store.mergeUpdate(alertId, { metadata: {
1160
+ ...metadata,
1161
+ push
1162
+ } });
964
1163
  }
965
1164
  /**
966
1165
  * Retry every critical alert whose push is still pending - at boot and when
@@ -968,19 +1167,10 @@ var AlertCenterAddon = class extends BaseAddon {
968
1167
  * delivered is skipped by its key, so reconciling never sends twice.
969
1168
  */
970
1169
  async reconcilePendingPushes() {
971
- const backend = this.ctx.api.settingsStore;
972
- if (!backend) return;
1170
+ const store = this.alertStore;
1171
+ if (store === null) return;
973
1172
  try {
974
- const rows = await backend.query.query({
975
- collection: ALERTS_COLLECTION,
976
- filter: {
977
- orderBy: {
978
- field: "updatedAt",
979
- direction: "desc"
980
- },
981
- limit: 500
982
- }
983
- });
1173
+ const rows = await store.listRecent(500);
984
1174
  for (const row of rows) {
985
1175
  const parsed = AlertSchema.safeParse({
986
1176
  id: row.id,
@@ -1007,12 +1197,9 @@ var AlertCenterAddon = class extends BaseAddon {
1007
1197
  const modelId = data.modelId ?? "unknown";
1008
1198
  const progress = data.progress ?? 0;
1009
1199
  const stableId = `model-download:${modelId}`;
1010
- const backend = this.ctx.api.settingsStore;
1011
- if (!backend) return;
1012
- if ((await backend.query.query({
1013
- collection: ALERTS_COLLECTION,
1014
- filter: { where: { id: stableId } }
1015
- })).length > 0) {
1200
+ const store = this.alertStore;
1201
+ if (store === null) return;
1202
+ if (await store.getData(stableId) !== null) {
1016
1203
  const now = Date.now();
1017
1204
  if (progress >= 100) {
1018
1205
  await this.mergeUpdate(stableId, {
@@ -1353,45 +1540,14 @@ var AlertCenterAddon = class extends BaseAddon {
1353
1540
  * so we must read the existing record, merge the patch, and write back.
1354
1541
  */
1355
1542
  async mergeUpdate(id, patch) {
1356
- const backend = this.ctx.api.settingsStore;
1357
- if (!backend) return;
1358
- const raw = await backend.get.query({
1359
- collection: ALERTS_COLLECTION,
1360
- key: id
1361
- });
1362
- if (raw === null || raw === void 0 || typeof raw !== "object") return;
1363
- const existing = Object.fromEntries(Object.entries(raw));
1364
- await backend.set.mutate({
1365
- collection: ALERTS_COLLECTION,
1366
- key: id,
1367
- value: {
1368
- ...existing,
1369
- ...patch
1370
- }
1371
- });
1543
+ const store = this.alertStore;
1544
+ if (store === null) return;
1545
+ await store.mergeUpdate(id, patch);
1372
1546
  }
1373
1547
  async persistAlert(alert) {
1374
- const backend = this.ctx.api.settingsStore;
1375
- if (!backend) return;
1376
- const data = {
1377
- id: alert.id,
1378
- category: alert.category,
1379
- severity: alert.severity,
1380
- title: alert.title,
1381
- message: alert.message,
1382
- status: alert.status,
1383
- read: alert.read,
1384
- createdAt: alert.createdAt,
1385
- updatedAt: alert.updatedAt,
1386
- ...alert.progress !== void 0 ? { progress: alert.progress } : {},
1387
- ...alert.source ? { source: alert.source } : {},
1388
- ...alert.metadata ? { metadata: alert.metadata } : {}
1389
- };
1390
- await backend.set.mutate({
1391
- collection: ALERTS_COLLECTION,
1392
- key: alert.id,
1393
- value: data
1394
- });
1548
+ const store = this.alertStore;
1549
+ if (store === null) return;
1550
+ await store.persist(alert);
1395
1551
  }
1396
1552
  emitAlertCreatedEvent(alert) {
1397
1553
  this.ctx.eventBus?.emit(createEvent("alert.created", EVENT_SOURCE, {
@@ -1411,36 +1567,18 @@ var AlertCenterAddon = class extends BaseAddon {
1411
1567
  }));
1412
1568
  }
1413
1569
  async enforceMaxAlerts() {
1414
- const backend = this.ctx.api.settingsStore;
1415
- if (!backend) return;
1416
- if (await backend.count.query({ collection: ALERTS_COLLECTION }) <= this.config.maxAlerts) return;
1417
- const all = await backend.query.query({
1418
- collection: ALERTS_COLLECTION,
1419
- filter: { orderBy: {
1420
- field: "createdAt",
1421
- direction: "asc"
1422
- } }
1423
- });
1424
- for (const id of selectOverflow(all.map(toPrunable), this.config.maxAlerts)) await backend.delete.mutate({
1425
- collection: ALERTS_COLLECTION,
1426
- key: id
1427
- });
1570
+ const store = this.alertStore;
1571
+ if (store === null) return;
1572
+ if (await store.countAll() <= this.config.maxAlerts) return;
1573
+ const all = await store.listAllByCreatedAtAsc();
1574
+ for (const id of selectOverflow(all.map(toPrunable), this.config.maxAlerts)) await store.delete(id);
1428
1575
  }
1429
1576
  async enforceRetention() {
1430
- const backend = this.ctx.api.settingsStore;
1431
- if (!backend) return;
1577
+ const store = this.alertStore;
1578
+ if (store === null) return;
1432
1579
  const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1e3;
1433
- const all = await backend.query.query({
1434
- collection: ALERTS_COLLECTION,
1435
- filter: { orderBy: {
1436
- field: "createdAt",
1437
- direction: "asc"
1438
- } }
1439
- });
1440
- for (const id of selectExpired(all.map(toPrunable), cutoff)) await backend.delete.mutate({
1441
- collection: ALERTS_COLLECTION,
1442
- key: id
1443
- });
1580
+ const all = await store.listAllByCreatedAtAsc();
1581
+ for (const id of selectExpired(all.map(toPrunable), cutoff)) await store.delete(id);
1444
1582
  }
1445
1583
  };
1446
1584
  //#endregion
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Record kinds owned by alert-center (records plan phase 4).
3
+ */
4
+ import { type Alert, type DefinedRecordKind } from "@camstack/types";
5
+ import { z } from "zod";
6
+ /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
7
+ export declare const ALERTS_COLLECTION = "alerts";
8
+ export type AlertBody = Omit<Alert, "id">;
9
+ export declare const AlertBodySchema: z.ZodType<AlertBody>;
10
+ export type AlertCenterRecordKindsMap = {
11
+ readonly alerts: DefinedRecordKind<z.ZodType<AlertBody>>;
12
+ };
13
+ export declare const alertCenterRecordKinds: AlertCenterRecordKindsMap;
14
+ /** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
15
+ export declare const alertsRecordKind: DefinedRecordKind<z.ZodType<AlertBody>>;
@@ -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-D1vECb_6.js");
6
+ const require_dist = require("../../dist-DgOG8flk.js");
7
7
  //#region src/builtins/autotrack/autotrack-config.ts
8
8
  var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
9
9
  deadZoneFraction: .5,
@@ -1,4 +1,4 @@
1
- import { $i as EventCategory, Fn as ptzAutotrackCapability, Fr as BaseAddon, N as FIRST_LEVEL_MACRO_CLASSES, Oi as isEvent, Pr as errMsg, dt as bareAddonId } from "../../dist-DERK-gP5.mjs";
1
+ import { Lr as errMsg, P as FIRST_LEVEL_MACRO_CLASSES, Pi as isEvent, Rr as BaseAddon, ht as bareAddonId, la as EventCategory, zn as ptzAutotrackCapability } from "../../dist-BNunRyXT.mjs";
2
2
  //#region src/builtins/autotrack/autotrack-config.ts
3
3
  var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
4
4
  deadZoneFraction: .5,
@@ -2,6 +2,7 @@ import type { ProviderRegistration } from "@camstack/types";
2
2
  import { BaseAddon } from "@camstack/types";
3
3
  export declare class BackupOrchestratorAddon extends BaseAddon<Record<string, never>> {
4
4
  private systemBackup;
5
+ private backupRecords;
5
6
  private policies;
6
7
  private schedules;
7
8
  /** Backup encryption keys — PUBLIC keys only (see encryption-key-store.ts). */