@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
@@ -3,7 +3,9 @@ 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
+ const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
+ const require_phase6_declare_gate = require("../../phase6-declare-gate-Ci1-8uUn.js");
7
9
  //#region src/builtins/alerts/critical-push.ts
8
10
  /** Alert categories that are critical system findings. */
9
11
  var CRITICAL_CATEGORIES = new Set([
@@ -282,6 +284,211 @@ function runnerPushLine(record) {
282
284
  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.`;
283
285
  }
284
286
  //#endregion
287
+ //#region src/builtins/alerts/record-kinds.ts
288
+ var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
289
+ /**
290
+ * Record kinds owned by alert-center (records plan phase 4).
291
+ */
292
+ /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
293
+ var ALERTS_COLLECTION = "alerts";
294
+ var AlertBodySchema = require_dist.AlertSchema.omit({ id: true });
295
+ var _alertCenterRecordKinds = require_dist.defineRecordKinds({ alerts: {
296
+ schema: AlertBodySchema,
297
+ class: "audit",
298
+ writeTrigger: "EventBus categories the alert center tracks, operator mark read/dismiss, and model-download progress merges",
299
+ device: "none",
300
+ at: "none",
301
+ indexes: [
302
+ {
303
+ name: "read",
304
+ fields: ["read"]
305
+ },
306
+ {
307
+ name: "created_at",
308
+ fields: ["createdAt"]
309
+ },
310
+ {
311
+ name: "updated_at",
312
+ fields: ["updatedAt"]
313
+ }
314
+ ],
315
+ retention: {
316
+ owner: "alert-center",
317
+ reason: "maxAlerts cap and retentionDays enforced on write (enforceMaxAlerts / enforceRetention); read alerts preferred when trimming overflow"
318
+ },
319
+ adoptsFrom: ALERTS_COLLECTION
320
+ } });
321
+ var alertCenterRecordKinds = _alertCenterRecordKinds;
322
+ /** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
323
+ var alertsRecordKind = _alertCenterRecordKinds.alerts;
324
+ //#endregion
325
+ //#region src/builtins/alerts/alert-store.ts
326
+ function toRecord(row) {
327
+ return {
328
+ id: row.id,
329
+ data: row.data
330
+ };
331
+ }
332
+ function toRecordFromLegacy(row) {
333
+ return {
334
+ id: row.id,
335
+ data: row.data
336
+ };
337
+ }
338
+ function isRecord(value) {
339
+ return typeof value === "object" && value !== null && !Array.isArray(value);
340
+ }
341
+ function legacyGetData(value) {
342
+ if (!isRecord(value)) return null;
343
+ if ("data" in value) {
344
+ const data = value.data;
345
+ return isRecord(data) ? data : null;
346
+ }
347
+ return value;
348
+ }
349
+ var AlertStore = class AlertStore {
350
+ kind;
351
+ legacyStore;
352
+ constructor(kind, legacyStore) {
353
+ this.kind = kind;
354
+ this.legacyStore = legacyStore;
355
+ }
356
+ static of(records) {
357
+ return new AlertStore(records.kind(alertsRecordKind), null);
358
+ }
359
+ static legacy(store) {
360
+ return new AlertStore(null, store);
361
+ }
362
+ async legacyRows() {
363
+ const store = this.legacyStore;
364
+ if (store === null) return [];
365
+ return (await store.query.query({
366
+ collection: ALERTS_COLLECTION,
367
+ filter: {}
368
+ })).map((row) => toRecordFromLegacy({
369
+ id: row.id,
370
+ data: row.data
371
+ }));
372
+ }
373
+ async list(filter) {
374
+ let out;
375
+ const kind = this.kind;
376
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
377
+ else out = [...await this.legacyRows()];
378
+ if (filter?.unreadOnly === true) out = out.filter((r) => r.data["read"] === false);
379
+ out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
380
+ const limit = filter?.limit ?? 100;
381
+ return out.slice(0, limit);
382
+ }
383
+ async countUnread() {
384
+ return (await this.list({
385
+ unreadOnly: true,
386
+ limit: 1e4
387
+ })).length;
388
+ }
389
+ async countAll() {
390
+ const kind = this.kind;
391
+ if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).length;
392
+ return (await this.legacyRows()).length;
393
+ }
394
+ async getData(id) {
395
+ const kind = this.kind;
396
+ if (kind !== null) {
397
+ const row = await kind.get(id);
398
+ if (row === null) return null;
399
+ return row.data;
400
+ }
401
+ const store = this.legacyStore;
402
+ if (store === null) return null;
403
+ return legacyGetData(await store.get.query({
404
+ collection: ALERTS_COLLECTION,
405
+ key: id
406
+ }));
407
+ }
408
+ async mergeUpdate(id, patch) {
409
+ const existing = await this.getData(id);
410
+ if (existing === null) return;
411
+ await this.putRaw(id, {
412
+ ...existing,
413
+ ...patch
414
+ });
415
+ }
416
+ async persist(alert) {
417
+ const { id, ...body } = alert;
418
+ const data = alertsRecordKind.schema.parse(body);
419
+ const kind = this.kind;
420
+ if (kind !== null) {
421
+ await kind.put({
422
+ id,
423
+ data
424
+ });
425
+ return;
426
+ }
427
+ await this.putRaw(id, {
428
+ ...body,
429
+ id
430
+ });
431
+ }
432
+ async putRaw(id, data) {
433
+ const { id: _drop, ...body } = require_dist.AlertSchema.parse({
434
+ id,
435
+ ...data
436
+ });
437
+ const kind = this.kind;
438
+ if (kind !== null) {
439
+ await kind.put({
440
+ id,
441
+ data: body
442
+ });
443
+ return;
444
+ }
445
+ const store = this.legacyStore;
446
+ if (store === null) return;
447
+ await store.set.mutate({
448
+ collection: ALERTS_COLLECTION,
449
+ key: id,
450
+ value: {
451
+ id,
452
+ ...body
453
+ }
454
+ });
455
+ }
456
+ async delete(id) {
457
+ const kind = this.kind;
458
+ if (kind !== null) {
459
+ await kind.delete(id);
460
+ return;
461
+ }
462
+ const store = this.legacyStore;
463
+ if (store === null) return;
464
+ await store.delete.mutate({
465
+ collection: ALERTS_COLLECTION,
466
+ key: id
467
+ });
468
+ }
469
+ async listAllByCreatedAtAsc() {
470
+ const kind = this.kind;
471
+ let out;
472
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind)).map(toRecord);
473
+ else out = [...await this.legacyRows()];
474
+ out.sort((a, b) => Number(a.data["createdAt"] ?? 0) - Number(b.data["createdAt"] ?? 0));
475
+ return out;
476
+ }
477
+ async listRecent(limit) {
478
+ const kind = this.kind;
479
+ let out;
480
+ if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
481
+ else out = [...await this.legacyRows()];
482
+ out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
483
+ return out.slice(0, limit);
484
+ }
485
+ async findWhereDataField(field, value) {
486
+ const kind = this.kind;
487
+ if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).filter((r) => r.data[field] === value).map(toRecord);
488
+ return (await this.legacyRows()).filter((r) => r.data[field] === value);
489
+ }
490
+ };
491
+ //#endregion
285
492
  //#region src/builtins/alerts/alerts.addon.ts
286
493
  var CATEGORY_MAPPINGS = {
287
494
  "addon.crashed": {
@@ -454,13 +661,18 @@ var DEFAULT_CONFIG = {
454
661
  maxAlerts: 500,
455
662
  retentionDays: 30,
456
663
  criticalPushEnabled: true,
457
- criticalPushTargetIds: ""
664
+ criticalPushTargetIds: []
458
665
  };
666
+ /** Accept the live `string[]` shape and the pre-multiselect CSV string. */
667
+ function normalizeCriticalPushTargetIds(raw) {
668
+ if (Array.isArray(raw)) return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim());
669
+ if (typeof raw === "string" && raw.trim().length > 0) return raw.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
670
+ return [];
671
+ }
459
672
  /** One burst of critical findings (a whole boot of refused runners) is ONE digest push. */
460
673
  var PUSH_COALESCE_MS = 2e3;
461
674
  /** Addons whose (re)start is a reason to retry pending critical pushes. */
462
675
  var PUSH_RECONCILE_ADDONS = new Set(["notifiers", "notification-center"]);
463
- var ALERTS_COLLECTION = "alerts";
464
676
  var EVENT_SOURCE = {
465
677
  type: "addon",
466
678
  id: "alert-center"
@@ -481,6 +693,7 @@ function toPrunable(record) {
481
693
  };
482
694
  }
483
695
  var AlertCenterAddon = class extends require_dist.BaseAddon {
696
+ alertStore = null;
484
697
  unsubscribers = [];
485
698
  /** How long a burst of critical findings is gathered into one digest push. */
486
699
  pushCoalesceMs;
@@ -495,6 +708,11 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
495
708
  */
496
709
  rateLimitCounters = /* @__PURE__ */ new Map();
497
710
  async onInitialize() {
711
+ const records = this.ctx.records;
712
+ const store = this.ctx.api?.settingsStore;
713
+ const useRecords = records !== void 0 && store !== void 0 && await require_phase6_declare_gate.resolvePhase6UseRecordsPathForHub(this.ctx, "alert-center", alertCenterRecordKinds, ["alerts"]);
714
+ this.alertStore = useRecords && records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
715
+ if (this.alertStore === null) throw new Error("alert-center needs ctx.records or settings-store on the hub");
498
716
  const alertsProvider = {
499
717
  emit: (alert) => this.emitAlert(alert),
500
718
  update: (input) => this.updateAlert(input.alertId, input.patch),
@@ -514,6 +732,7 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
514
732
  this.unsubscribers = unsubs;
515
733
  this.reconcilePendingPushes();
516
734
  this.dismissLegacyStreamCards(void 0);
735
+ this.migrateCriticalPushTargetIds();
517
736
  this.ctx.logger.info("Initialized", { meta: { trackedCategoriesCount: TRACKED_CATEGORIES.length } });
518
737
  return [{
519
738
  capability: require_dist.alertsCapability,
@@ -561,43 +780,28 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
561
780
  type: "boolean",
562
781
  key: "criticalPushEnabled",
563
782
  label: "Push critical system alerts",
564
- 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.",
783
+ 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.",
565
784
  default: true
566
785
  }),
567
786
  this.field({
568
- type: "text",
787
+ type: "notification-target-multiselect",
569
788
  key: "criticalPushTargetIds",
570
789
  label: "Critical push targets",
571
- description: "Comma-separated notifier target ids. Empty = every enabled shared (not personal) target.",
572
- default: ""
790
+ description: "Notifier targets that receive critical system alerts. Empty = every enabled shared (not personal) target.",
791
+ default: []
573
792
  })
574
793
  ]
575
794
  }] });
576
795
  }
577
796
  async listAlerts(filter) {
578
- const backend = this.ctx.api.settingsStore;
579
- if (!backend) return [];
580
- const whereClause = {};
581
- if (filter?.unreadOnly) whereClause.read = false;
582
- return (await backend.query.query({
583
- collection: ALERTS_COLLECTION,
584
- filter: {
585
- where: Object.keys(whereClause).length > 0 ? whereClause : void 0,
586
- orderBy: {
587
- field: "updatedAt",
588
- direction: "desc"
589
- },
590
- limit: filter?.limit ?? 100
591
- }
592
- })).map(parseAlert);
797
+ const store = this.alertStore;
798
+ if (store === null) return [];
799
+ return (await store.list(filter)).map(parseAlert);
593
800
  }
594
801
  async getUnreadCount() {
595
- const backend = this.ctx.api.settingsStore;
596
- if (!backend) return 0;
597
- return backend.count.query({
598
- collection: ALERTS_COLLECTION,
599
- filter: { where: { read: false } }
600
- });
802
+ const store = this.alertStore;
803
+ if (store === null) return 0;
804
+ return store.countUnread();
601
805
  }
602
806
  async markRead(alertId) {
603
807
  await this.mergeUpdate(alertId, {
@@ -606,11 +810,11 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
606
810
  });
607
811
  }
608
812
  async markAllRead() {
609
- const backend = this.ctx.api.settingsStore;
610
- if (!backend) return;
611
- const unread = await backend.query.query({
612
- collection: ALERTS_COLLECTION,
613
- filter: { where: { read: false } }
813
+ const store = this.alertStore;
814
+ if (store === null) return;
815
+ const unread = await store.list({
816
+ unreadOnly: true,
817
+ limit: 1e4
614
818
  });
615
819
  const now = Date.now();
616
820
  for (const record of unread) await this.mergeUpdate(record.id, {
@@ -707,14 +911,14 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
707
911
  }
708
912
  }
709
913
  async readRunnerRecord(alertId) {
710
- const backend = this.ctx.api.settingsStore;
711
- if (!backend) return null;
712
- const raw = await backend.get.query({
713
- collection: ALERTS_COLLECTION,
714
- key: alertId
914
+ const store = this.alertStore;
915
+ if (store === null) return null;
916
+ const raw = await store.getData(alertId);
917
+ if (raw === null) return null;
918
+ const alert = require_dist.AlertSchema.safeParse({
919
+ id: alertId,
920
+ ...raw
715
921
  });
716
- if (raw === null || raw === void 0 || typeof raw !== "object") return null;
717
- const alert = require_dist.AlertSchema.safeParse(raw);
718
922
  if (!alert.success || alert.data.status === "dismissed") return null;
719
923
  return parseRunnerRecord(alert.data.metadata?.["runner"]);
720
924
  }
@@ -842,13 +1046,10 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
842
1046
  });
843
1047
  }
844
1048
  async readAlertRaw(alertId) {
845
- const backend = this.ctx.api.settingsStore;
846
- if (!backend) return null;
847
- const raw = await backend.get.query({
848
- collection: ALERTS_COLLECTION,
849
- key: alertId
850
- });
851
- if (raw === null || raw === void 0 || typeof raw !== "object") return null;
1049
+ const store = this.alertStore;
1050
+ if (store === null) return null;
1051
+ const raw = await store.getData(alertId);
1052
+ if (raw === null) return null;
852
1053
  const rec = Object.fromEntries(Object.entries(raw));
853
1054
  const meta = rec["metadata"];
854
1055
  const push = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta["push"] : void 0;
@@ -866,9 +1067,19 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
866
1067
  pushPolicy() {
867
1068
  return {
868
1069
  enabled: this.config.criticalPushEnabled,
869
- targetIds: this.config.criticalPushTargetIds.split(",").map((id) => id.trim()).filter((id) => id.length > 0)
1070
+ targetIds: normalizeCriticalPushTargetIds(this.config.criticalPushTargetIds)
870
1071
  };
871
1072
  }
1073
+ /** Rewrite a legacy CSV `criticalPushTargetIds` string into `string[]`. */
1074
+ async migrateCriticalPushTargetIds() {
1075
+ const raw = this.config.criticalPushTargetIds;
1076
+ if (typeof raw !== "string") return;
1077
+ try {
1078
+ await this.updateGlobalSettings({ criticalPushTargetIds: normalizeCriticalPushTargetIds(raw) });
1079
+ } catch (err) {
1080
+ this.ctx.logger.warn("criticalPushTargetIds CSV migration failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
1081
+ }
1082
+ }
872
1083
  pushPorts() {
873
1084
  const api = this.ctx.api;
874
1085
  return {
@@ -945,27 +1156,16 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
945
1156
  return this.pushChain;
946
1157
  }
947
1158
  async storePushState(alertId, push) {
948
- const backend = this.ctx.api.settingsStore;
949
- if (!backend) return;
950
- const raw = await backend.get.query({
951
- collection: ALERTS_COLLECTION,
952
- key: alertId
953
- });
954
- if (raw === null || raw === void 0 || typeof raw !== "object") return;
955
- const existing = Object.fromEntries(Object.entries(raw));
956
- const meta = existing["metadata"];
1159
+ const store = this.alertStore;
1160
+ if (store === null) return;
1161
+ const raw = await store.getData(alertId);
1162
+ if (raw === null) return;
1163
+ const meta = raw["metadata"];
957
1164
  const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : {};
958
- await backend.set.mutate({
959
- collection: ALERTS_COLLECTION,
960
- key: alertId,
961
- value: {
962
- ...existing,
963
- metadata: {
964
- ...metadata,
965
- push
966
- }
967
- }
968
- });
1165
+ await store.mergeUpdate(alertId, { metadata: {
1166
+ ...metadata,
1167
+ push
1168
+ } });
969
1169
  }
970
1170
  /**
971
1171
  * Retry every critical alert whose push is still pending - at boot and when
@@ -973,19 +1173,10 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
973
1173
  * delivered is skipped by its key, so reconciling never sends twice.
974
1174
  */
975
1175
  async reconcilePendingPushes() {
976
- const backend = this.ctx.api.settingsStore;
977
- if (!backend) return;
1176
+ const store = this.alertStore;
1177
+ if (store === null) return;
978
1178
  try {
979
- const rows = await backend.query.query({
980
- collection: ALERTS_COLLECTION,
981
- filter: {
982
- orderBy: {
983
- field: "updatedAt",
984
- direction: "desc"
985
- },
986
- limit: 500
987
- }
988
- });
1179
+ const rows = await store.listRecent(500);
989
1180
  for (const row of rows) {
990
1181
  const parsed = require_dist.AlertSchema.safeParse({
991
1182
  id: row.id,
@@ -1012,12 +1203,9 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
1012
1203
  const modelId = data.modelId ?? "unknown";
1013
1204
  const progress = data.progress ?? 0;
1014
1205
  const stableId = `model-download:${modelId}`;
1015
- const backend = this.ctx.api.settingsStore;
1016
- if (!backend) return;
1017
- if ((await backend.query.query({
1018
- collection: ALERTS_COLLECTION,
1019
- filter: { where: { id: stableId } }
1020
- })).length > 0) {
1206
+ const store = this.alertStore;
1207
+ if (store === null) return;
1208
+ if (await store.getData(stableId) !== null) {
1021
1209
  const now = Date.now();
1022
1210
  if (progress >= 100) {
1023
1211
  await this.mergeUpdate(stableId, {
@@ -1358,45 +1546,14 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
1358
1546
  * so we must read the existing record, merge the patch, and write back.
1359
1547
  */
1360
1548
  async mergeUpdate(id, patch) {
1361
- const backend = this.ctx.api.settingsStore;
1362
- if (!backend) return;
1363
- const raw = await backend.get.query({
1364
- collection: ALERTS_COLLECTION,
1365
- key: id
1366
- });
1367
- if (raw === null || raw === void 0 || typeof raw !== "object") return;
1368
- const existing = Object.fromEntries(Object.entries(raw));
1369
- await backend.set.mutate({
1370
- collection: ALERTS_COLLECTION,
1371
- key: id,
1372
- value: {
1373
- ...existing,
1374
- ...patch
1375
- }
1376
- });
1549
+ const store = this.alertStore;
1550
+ if (store === null) return;
1551
+ await store.mergeUpdate(id, patch);
1377
1552
  }
1378
1553
  async persistAlert(alert) {
1379
- const backend = this.ctx.api.settingsStore;
1380
- if (!backend) return;
1381
- const data = {
1382
- id: alert.id,
1383
- category: alert.category,
1384
- severity: alert.severity,
1385
- title: alert.title,
1386
- message: alert.message,
1387
- status: alert.status,
1388
- read: alert.read,
1389
- createdAt: alert.createdAt,
1390
- updatedAt: alert.updatedAt,
1391
- ...alert.progress !== void 0 ? { progress: alert.progress } : {},
1392
- ...alert.source ? { source: alert.source } : {},
1393
- ...alert.metadata ? { metadata: alert.metadata } : {}
1394
- };
1395
- await backend.set.mutate({
1396
- collection: ALERTS_COLLECTION,
1397
- key: alert.id,
1398
- value: data
1399
- });
1554
+ const store = this.alertStore;
1555
+ if (store === null) return;
1556
+ await store.persist(alert);
1400
1557
  }
1401
1558
  emitAlertCreatedEvent(alert) {
1402
1559
  this.ctx.eventBus?.emit(require_dist.createEvent("alert.created", EVENT_SOURCE, {
@@ -1416,36 +1573,18 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
1416
1573
  }));
1417
1574
  }
1418
1575
  async enforceMaxAlerts() {
1419
- const backend = this.ctx.api.settingsStore;
1420
- if (!backend) return;
1421
- if (await backend.count.query({ collection: ALERTS_COLLECTION }) <= this.config.maxAlerts) return;
1422
- const all = await backend.query.query({
1423
- collection: ALERTS_COLLECTION,
1424
- filter: { orderBy: {
1425
- field: "createdAt",
1426
- direction: "asc"
1427
- } }
1428
- });
1429
- for (const id of selectOverflow(all.map(toPrunable), this.config.maxAlerts)) await backend.delete.mutate({
1430
- collection: ALERTS_COLLECTION,
1431
- key: id
1432
- });
1576
+ const store = this.alertStore;
1577
+ if (store === null) return;
1578
+ if (await store.countAll() <= this.config.maxAlerts) return;
1579
+ const all = await store.listAllByCreatedAtAsc();
1580
+ for (const id of selectOverflow(all.map(toPrunable), this.config.maxAlerts)) await store.delete(id);
1433
1581
  }
1434
1582
  async enforceRetention() {
1435
- const backend = this.ctx.api.settingsStore;
1436
- if (!backend) return;
1583
+ const store = this.alertStore;
1584
+ if (store === null) return;
1437
1585
  const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1e3;
1438
- const all = await backend.query.query({
1439
- collection: ALERTS_COLLECTION,
1440
- filter: { orderBy: {
1441
- field: "createdAt",
1442
- direction: "asc"
1443
- } }
1444
- });
1445
- for (const id of selectExpired(all.map(toPrunable), cutoff)) await backend.delete.mutate({
1446
- collection: ALERTS_COLLECTION,
1447
- key: id
1448
- });
1586
+ const all = await store.listAllByCreatedAtAsc();
1587
+ for (const id of selectExpired(all.map(toPrunable), cutoff)) await store.delete(id);
1449
1588
  }
1450
1589
  };
1451
1590
  //#endregion