@camstack/system 1.2.444 → 1.2.446
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.
- package/dist/addon-runner.js +40 -31
- package/dist/addon-runner.mjs +41 -32
- package/dist/{agent-https-DlpTMDqA.js → agent-https-5DYAOJMO.js} +810 -12
- package/dist/{agent-https-U0d4uvn2.mjs → agent-https-BWUEf6ev.mjs} +697 -13
- package/dist/auth/admin-token-manager.d.ts +9 -3
- package/dist/auth/api-key-manager.d.ts +9 -3
- package/dist/auth/auth-audit-log.d.ts +9 -3
- package/dist/auth/device-credential-manager.d.ts +5 -1
- package/dist/auth/external-identity-manager.d.ts +8 -21
- package/dist/auth/login-session-manager.d.ts +11 -3
- package/dist/auth/scoped-token-manager.d.ts +8 -52
- package/dist/auth/totp-manager.d.ts +11 -3
- package/dist/auth/user-manager.d.ts +10 -17
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alert-store.d.ts +32 -0
- package/dist/builtins/alerts/alerts.addon.d.ts +9 -2
- package/dist/builtins/alerts/alerts.addon.js +373 -154
- package/dist/builtins/alerts/alerts.addon.mjs +372 -154
- package/dist/builtins/alerts/critical-push.d.ts +4 -0
- package/dist/builtins/alerts/emit-alert-policy.d.ts +28 -0
- package/dist/builtins/alerts/record-kinds.d.ts +15 -0
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +134 -193
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +134 -193
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/encryption-key-store.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/record-kinds.d.ts +58 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +4 -2
- package/dist/builtins/calendars/calendar-prefs-store.d.ts +13 -5
- package/dist/builtins/calendars/calendars.addon.d.ts +2 -2
- package/dist/builtins/calendars/calendars.addon.js +67 -64
- package/dist/builtins/calendars/calendars.addon.mjs +59 -64
- package/dist/builtins/calendars/record-kinds.d.ts +18 -0
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/cluster-agent/record-kinds.d.ts +36 -0
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/block-settings-store.d.ts +8 -4
- package/dist/builtins/core-blocks/core-block-store.d.ts +8 -16
- package/dist/builtins/core-blocks/core-blocks.addon.js +85 -112
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +86 -113
- package/dist/builtins/core-blocks/index.mjs +1 -1
- package/dist/builtins/core-blocks/record-kinds.d.ts +26 -0
- package/dist/builtins/device-manager/device-manager.addon.js +111 -187
- package/dist/builtins/device-manager/device-manager.addon.mjs +110 -187
- package/dist/builtins/device-manager/device-tombstone-store.d.ts +9 -48
- package/dist/builtins/device-manager/record-kinds.d.ts +14 -0
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +152 -22
- package/dist/builtins/keychain/index.mjs +152 -22
- package/dist/builtins/keychain/keychain-service.d.ts +3 -2
- package/dist/builtins/keychain/keychain-store.d.ts +13 -2
- package/dist/builtins/keychain/record-kinds.d.ts +16 -0
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/auth-schema.d.ts +3 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2903 -2123
- package/dist/builtins/local-auth/local-auth.addon.mjs +2904 -2124
- package/dist/builtins/local-auth/oauth-session-manager.d.ts +8 -48
- package/dist/builtins/local-auth/record-kinds.d.ts +141 -0
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/record-entries/index.js +1 -1
- package/dist/builtins/record-entries/index.mjs +1 -1
- package/dist/builtins/records/legacy-table-row-count.d.ts +5 -0
- package/dist/builtins/records/phase6-declare-gate.d.ts +28 -0
- package/dist/builtins/records-isolated.d.ts +10 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/integration-record-kinds.d.ts +30 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -16
- package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +6 -0
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/records-engine.d.ts +4 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +5 -1
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +17 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +111 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +111 -3
- package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +9 -1
- package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +5 -2
- package/dist/builtins/storage-orchestrator/location-store.d.ts +7 -2
- package/dist/builtins/storage-orchestrator/record-kinds.d.ts +38 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +196 -5
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +195 -6
- package/dist/builtins/system-config/record-kinds.d.ts +32 -0
- package/dist/builtins/system-config/system-config.addon.js +53 -618
- package/dist/builtins/system-config/system-config.addon.mjs +29 -577
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-C3rKncIF.mjs → composition-sources-BmC5jAUv.mjs} +1 -1
- package/dist/{composition-sources-NAPZddic.js → composition-sources-BwIIltnZ.js} +1 -1
- package/dist/{constants-BKX2QnIg.mjs → constants-6XHGmEUF.mjs} +1 -1
- package/dist/{constants-BXiNEIeV.js → constants-DA_tjzIk.js} +1 -1
- package/dist/{device-ca-jxjSL8Ov.mjs → device-ca-Bh_ClxMO.mjs} +1 -1
- package/dist/{device-ca-DT9X2S6d.js → device-ca-CnbrgfmW.js} +1 -1
- package/dist/{dist-D1vECb_6.js → dist-BkNfEJKa.js} +521 -64
- package/dist/{dist-DERK-gP5.mjs → dist-CkZIrsAP.mjs} +462 -65
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-CRaC97V0.mjs → hub-mdns-ciao-CoyIUWHC.mjs} +2 -2
- package/dist/{hub-mdns-ciao-Cah9GCIg.js → hub-mdns-ciao-m5LIr4oA.js} +2 -2
- package/dist/index.d.ts +7 -0
- package/dist/index.js +3095 -2821
- package/dist/index.mjs +3067 -2810
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/moleculer/event-bus.d.ts +3 -1
- package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +5 -1
- package/dist/kernel/moleculer/remote-logger.d.ts +2 -2
- package/dist/kernel/transport/cap-route-resolver.d.ts +9 -38
- package/dist/phase6-declare-gate-BDWZuB2n.mjs +93 -0
- package/dist/phase6-declare-gate-Bl7KocEs.js +98 -0
- package/dist/read-all-rows-CVoO1ONM.js +29 -0
- package/dist/read-all-rows-TaPqdWNF.mjs +25 -0
- package/dist/records/read-all-rows.d.ts +6 -0
- package/dist/{restore-archive-Dy-qKTdF.js → restore-archive-B57xI5Ue.js} +353 -5
- package/dist/{restore-archive-daKyE24F.mjs → restore-archive-CMr4V7Fi.mjs} +339 -9
- package/dist/tls/agent-https-names.d.ts +9 -13
- package/dist/{wal-maintenance-zRc24mOC.mjs → wal-maintenance-Bqm4zrNA.mjs} +0 -0
- package/dist/{wal-maintenance-dAv4IdzC.js → wal-maintenance-CuG1DUca.js} +0 -0
- package/package.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
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-CkZIrsAP.mjs";
|
|
2
|
+
import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
|
|
3
|
+
import { t as resolvePhase6UseRecordsPathForHub } from "../../phase6-declare-gate-BDWZuB2n.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([
|
|
@@ -6,6 +8,9 @@ var CRITICAL_CATEGORIES = new Set([
|
|
|
6
8
|
"addon.runner-refused",
|
|
7
9
|
"system.runner-check"
|
|
8
10
|
]);
|
|
11
|
+
function isCriticalPush(alert) {
|
|
12
|
+
return alert.severity === "critical" || CRITICAL_CATEGORIES.has(alert.category);
|
|
13
|
+
}
|
|
9
14
|
function isPushState(value) {
|
|
10
15
|
if (typeof value !== "object" || value === null) return false;
|
|
11
16
|
const rec = value;
|
|
@@ -103,6 +108,59 @@ async function deliverDigest(input) {
|
|
|
103
108
|
return out;
|
|
104
109
|
}
|
|
105
110
|
//#endregion
|
|
111
|
+
//#region src/builtins/alerts/emit-alert-policy.ts
|
|
112
|
+
function episodeKeyFromMetadata(metadata) {
|
|
113
|
+
const key = metadata?.["episodeKey"];
|
|
114
|
+
return typeof key === "string" ? key : void 0;
|
|
115
|
+
}
|
|
116
|
+
/** Completed episodes start fresh — prior push must not suppress the next digest. */
|
|
117
|
+
function shouldDropPriorPush(existingStatus) {
|
|
118
|
+
return existingStatus === "completed";
|
|
119
|
+
}
|
|
120
|
+
function alertWithRetainedPush(toStore, existingPush, existingStatus) {
|
|
121
|
+
if (existingPush === void 0 || shouldDropPriorPush(existingStatus)) return toStore;
|
|
122
|
+
return {
|
|
123
|
+
...toStore,
|
|
124
|
+
metadata: {
|
|
125
|
+
...toStore.metadata,
|
|
126
|
+
push: existingPush
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Re-emit of the same alert id: preserve read when the episode is unchanged
|
|
132
|
+
* and still active. A completed episode starts again. Queue a critical push
|
|
133
|
+
* only for active, unread critical findings.
|
|
134
|
+
*/
|
|
135
|
+
function mergeEmitAlert(input) {
|
|
136
|
+
const incomingKey = episodeKeyFromMetadata(input.incoming.metadata);
|
|
137
|
+
const existingKey = input.existing?.episodeKey;
|
|
138
|
+
if (input.existing?.read === true) {
|
|
139
|
+
const sameEpisode = incomingKey === void 0 || incomingKey === existingKey;
|
|
140
|
+
const priorCompleted = input.existing.status === "completed";
|
|
141
|
+
if (sameEpisode && !priorCompleted) return {
|
|
142
|
+
alert: {
|
|
143
|
+
...input.incoming,
|
|
144
|
+
read: true
|
|
145
|
+
},
|
|
146
|
+
queuePush: false
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const queuePush = isCriticalPush(input.incoming) && input.incoming.status === "active" && input.incoming.read === false;
|
|
150
|
+
return {
|
|
151
|
+
alert: input.incoming,
|
|
152
|
+
queuePush
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function criticalPushPayload(alert) {
|
|
156
|
+
const key = episodeKeyFromMetadata(alert.metadata) ?? alert.id;
|
|
157
|
+
const pushLine = alert.metadata?.["pushLine"];
|
|
158
|
+
return {
|
|
159
|
+
key,
|
|
160
|
+
line: typeof pushLine === "string" ? pushLine : alert.title
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
106
164
|
//#region src/builtins/alerts/device-label.ts
|
|
107
165
|
/**
|
|
108
166
|
* Operator-facing device label for alert messages.
|
|
@@ -277,6 +335,210 @@ function runnerPushLine(record) {
|
|
|
277
335
|
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
336
|
}
|
|
279
337
|
//#endregion
|
|
338
|
+
//#region src/builtins/alerts/record-kinds.ts
|
|
339
|
+
var import_read_all_rows = require_read_all_rows();
|
|
340
|
+
/**
|
|
341
|
+
* Record kinds owned by alert-center (records plan phase 4).
|
|
342
|
+
*/
|
|
343
|
+
/** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
|
|
344
|
+
var ALERTS_COLLECTION = "alerts";
|
|
345
|
+
var _alertCenterRecordKinds = defineRecordKinds({ alerts: {
|
|
346
|
+
schema: AlertSchema.omit({ id: true }),
|
|
347
|
+
class: "audit",
|
|
348
|
+
writeTrigger: "EventBus categories the alert center tracks, operator mark read/dismiss, and model-download progress merges",
|
|
349
|
+
device: "none",
|
|
350
|
+
at: "none",
|
|
351
|
+
indexes: [
|
|
352
|
+
{
|
|
353
|
+
name: "read",
|
|
354
|
+
fields: ["read"]
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: "created_at",
|
|
358
|
+
fields: ["createdAt"]
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: "updated_at",
|
|
362
|
+
fields: ["updatedAt"]
|
|
363
|
+
}
|
|
364
|
+
],
|
|
365
|
+
retention: {
|
|
366
|
+
owner: "alert-center",
|
|
367
|
+
reason: "maxAlerts cap and retentionDays enforced on write (enforceMaxAlerts / enforceRetention); read alerts preferred when trimming overflow"
|
|
368
|
+
},
|
|
369
|
+
adoptsFrom: ALERTS_COLLECTION
|
|
370
|
+
} });
|
|
371
|
+
var alertCenterRecordKinds = _alertCenterRecordKinds;
|
|
372
|
+
/** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
|
|
373
|
+
var alertsRecordKind = _alertCenterRecordKinds.alerts;
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/builtins/alerts/alert-store.ts
|
|
376
|
+
function toRecord(row) {
|
|
377
|
+
return {
|
|
378
|
+
id: row.id,
|
|
379
|
+
data: row.data
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function toRecordFromLegacy(row) {
|
|
383
|
+
return {
|
|
384
|
+
id: row.id,
|
|
385
|
+
data: row.data
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function isRecord(value) {
|
|
389
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
390
|
+
}
|
|
391
|
+
function legacyGetData(value) {
|
|
392
|
+
if (!isRecord(value)) return null;
|
|
393
|
+
if ("data" in value) {
|
|
394
|
+
const data = value.data;
|
|
395
|
+
return isRecord(data) ? data : null;
|
|
396
|
+
}
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
var AlertStore = class AlertStore {
|
|
400
|
+
kind;
|
|
401
|
+
legacyStore;
|
|
402
|
+
constructor(kind, legacyStore) {
|
|
403
|
+
this.kind = kind;
|
|
404
|
+
this.legacyStore = legacyStore;
|
|
405
|
+
}
|
|
406
|
+
static of(records) {
|
|
407
|
+
return new AlertStore(records.kind(alertsRecordKind), null);
|
|
408
|
+
}
|
|
409
|
+
static legacy(store) {
|
|
410
|
+
return new AlertStore(null, store);
|
|
411
|
+
}
|
|
412
|
+
async legacyRows() {
|
|
413
|
+
const store = this.legacyStore;
|
|
414
|
+
if (store === null) return [];
|
|
415
|
+
return (await store.query.query({
|
|
416
|
+
collection: ALERTS_COLLECTION,
|
|
417
|
+
filter: {}
|
|
418
|
+
})).map((row) => toRecordFromLegacy({
|
|
419
|
+
id: row.id,
|
|
420
|
+
data: row.data
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
async list(filter) {
|
|
424
|
+
let out;
|
|
425
|
+
const kind = this.kind;
|
|
426
|
+
if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
|
|
427
|
+
else out = [...await this.legacyRows()];
|
|
428
|
+
if (filter?.unreadOnly === true) out = out.filter((r) => r.data["read"] === false);
|
|
429
|
+
out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
|
|
430
|
+
const limit = filter?.limit ?? 100;
|
|
431
|
+
return out.slice(0, limit);
|
|
432
|
+
}
|
|
433
|
+
async countUnread() {
|
|
434
|
+
return (await this.list({
|
|
435
|
+
unreadOnly: true,
|
|
436
|
+
limit: 1e4
|
|
437
|
+
})).length;
|
|
438
|
+
}
|
|
439
|
+
async countAll() {
|
|
440
|
+
const kind = this.kind;
|
|
441
|
+
if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).length;
|
|
442
|
+
return (await this.legacyRows()).length;
|
|
443
|
+
}
|
|
444
|
+
async getData(id) {
|
|
445
|
+
const kind = this.kind;
|
|
446
|
+
if (kind !== null) {
|
|
447
|
+
const row = await kind.get(id);
|
|
448
|
+
if (row === null) return null;
|
|
449
|
+
return row.data;
|
|
450
|
+
}
|
|
451
|
+
const store = this.legacyStore;
|
|
452
|
+
if (store === null) return null;
|
|
453
|
+
return legacyGetData(await store.get.query({
|
|
454
|
+
collection: ALERTS_COLLECTION,
|
|
455
|
+
key: id
|
|
456
|
+
}));
|
|
457
|
+
}
|
|
458
|
+
async mergeUpdate(id, patch) {
|
|
459
|
+
const existing = await this.getData(id);
|
|
460
|
+
if (existing === null) return;
|
|
461
|
+
await this.putRaw(id, {
|
|
462
|
+
...existing,
|
|
463
|
+
...patch
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
async persist(alert) {
|
|
467
|
+
const { id, ...body } = alert;
|
|
468
|
+
const data = alertsRecordKind.schema.parse(body);
|
|
469
|
+
const kind = this.kind;
|
|
470
|
+
if (kind !== null) {
|
|
471
|
+
await kind.put({
|
|
472
|
+
id,
|
|
473
|
+
data
|
|
474
|
+
});
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
await this.putRaw(id, {
|
|
478
|
+
...body,
|
|
479
|
+
id
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
async putRaw(id, data) {
|
|
483
|
+
const { id: _drop, ...body } = AlertSchema.parse({
|
|
484
|
+
id,
|
|
485
|
+
...data
|
|
486
|
+
});
|
|
487
|
+
const kind = this.kind;
|
|
488
|
+
if (kind !== null) {
|
|
489
|
+
await kind.put({
|
|
490
|
+
id,
|
|
491
|
+
data: body
|
|
492
|
+
});
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const store = this.legacyStore;
|
|
496
|
+
if (store === null) return;
|
|
497
|
+
await store.set.mutate({
|
|
498
|
+
collection: ALERTS_COLLECTION,
|
|
499
|
+
key: id,
|
|
500
|
+
value: {
|
|
501
|
+
id,
|
|
502
|
+
...body
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
async delete(id) {
|
|
507
|
+
const kind = this.kind;
|
|
508
|
+
if (kind !== null) {
|
|
509
|
+
await kind.delete(id);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const store = this.legacyStore;
|
|
513
|
+
if (store === null) return;
|
|
514
|
+
await store.delete.mutate({
|
|
515
|
+
collection: ALERTS_COLLECTION,
|
|
516
|
+
key: id
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
async listAllByCreatedAtAsc() {
|
|
520
|
+
const kind = this.kind;
|
|
521
|
+
let out;
|
|
522
|
+
if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind)).map(toRecord);
|
|
523
|
+
else out = [...await this.legacyRows()];
|
|
524
|
+
out.sort((a, b) => Number(a.data["createdAt"] ?? 0) - Number(b.data["createdAt"] ?? 0));
|
|
525
|
+
return out;
|
|
526
|
+
}
|
|
527
|
+
async listRecent(limit) {
|
|
528
|
+
const kind = this.kind;
|
|
529
|
+
let out;
|
|
530
|
+
if (kind !== null) out = (await (0, import_read_all_rows.readAllRows)(kind, { order: "id" })).map(toRecord);
|
|
531
|
+
else out = [...await this.legacyRows()];
|
|
532
|
+
out.sort((a, b) => Number(b.data["updatedAt"] ?? 0) - Number(a.data["updatedAt"] ?? 0));
|
|
533
|
+
return out.slice(0, limit);
|
|
534
|
+
}
|
|
535
|
+
async findWhereDataField(field, value) {
|
|
536
|
+
const kind = this.kind;
|
|
537
|
+
if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).filter((r) => r.data[field] === value).map(toRecord);
|
|
538
|
+
return (await this.legacyRows()).filter((r) => r.data[field] === value);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
//#endregion
|
|
280
542
|
//#region src/builtins/alerts/alerts.addon.ts
|
|
281
543
|
var CATEGORY_MAPPINGS = {
|
|
282
544
|
"addon.crashed": {
|
|
@@ -449,13 +711,18 @@ var DEFAULT_CONFIG = {
|
|
|
449
711
|
maxAlerts: 500,
|
|
450
712
|
retentionDays: 30,
|
|
451
713
|
criticalPushEnabled: true,
|
|
452
|
-
criticalPushTargetIds:
|
|
714
|
+
criticalPushTargetIds: []
|
|
453
715
|
};
|
|
716
|
+
/** Accept the live `string[]` shape and the pre-multiselect CSV string. */
|
|
717
|
+
function normalizeCriticalPushTargetIds(raw) {
|
|
718
|
+
if (Array.isArray(raw)) return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim());
|
|
719
|
+
if (typeof raw === "string" && raw.trim().length > 0) return raw.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
720
|
+
return [];
|
|
721
|
+
}
|
|
454
722
|
/** One burst of critical findings (a whole boot of refused runners) is ONE digest push. */
|
|
455
723
|
var PUSH_COALESCE_MS = 2e3;
|
|
456
724
|
/** Addons whose (re)start is a reason to retry pending critical pushes. */
|
|
457
725
|
var PUSH_RECONCILE_ADDONS = new Set(["notifiers", "notification-center"]);
|
|
458
|
-
var ALERTS_COLLECTION = "alerts";
|
|
459
726
|
var EVENT_SOURCE = {
|
|
460
727
|
type: "addon",
|
|
461
728
|
id: "alert-center"
|
|
@@ -476,6 +743,7 @@ function toPrunable(record) {
|
|
|
476
743
|
};
|
|
477
744
|
}
|
|
478
745
|
var AlertCenterAddon = class extends BaseAddon {
|
|
746
|
+
alertStore = null;
|
|
479
747
|
unsubscribers = [];
|
|
480
748
|
/** How long a burst of critical findings is gathered into one digest push. */
|
|
481
749
|
pushCoalesceMs;
|
|
@@ -490,6 +758,11 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
490
758
|
*/
|
|
491
759
|
rateLimitCounters = /* @__PURE__ */ new Map();
|
|
492
760
|
async onInitialize() {
|
|
761
|
+
const records = this.ctx.records;
|
|
762
|
+
const store = this.ctx.api?.settingsStore;
|
|
763
|
+
const useRecords = records !== void 0 && store !== void 0 && await resolvePhase6UseRecordsPathForHub(this.ctx, "alert-center", alertCenterRecordKinds, ["alerts"]);
|
|
764
|
+
this.alertStore = useRecords && records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
|
|
765
|
+
if (this.alertStore === null) throw new Error("alert-center needs ctx.records or settings-store on the hub");
|
|
493
766
|
const alertsProvider = {
|
|
494
767
|
emit: (alert) => this.emitAlert(alert),
|
|
495
768
|
update: (input) => this.updateAlert(input.alertId, input.patch),
|
|
@@ -509,6 +782,7 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
509
782
|
this.unsubscribers = unsubs;
|
|
510
783
|
this.reconcilePendingPushes();
|
|
511
784
|
this.dismissLegacyStreamCards(void 0);
|
|
785
|
+
this.migrateCriticalPushTargetIds();
|
|
512
786
|
this.ctx.logger.info("Initialized", { meta: { trackedCategoriesCount: TRACKED_CATEGORIES.length } });
|
|
513
787
|
return [{
|
|
514
788
|
capability: alertsCapability,
|
|
@@ -556,43 +830,28 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
556
830
|
type: "boolean",
|
|
557
831
|
key: "criticalPushEnabled",
|
|
558
832
|
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
|
|
833
|
+
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
834
|
default: true
|
|
561
835
|
}),
|
|
562
836
|
this.field({
|
|
563
|
-
type: "
|
|
837
|
+
type: "notification-target-multiselect",
|
|
564
838
|
key: "criticalPushTargetIds",
|
|
565
839
|
label: "Critical push targets",
|
|
566
|
-
description: "
|
|
567
|
-
default:
|
|
840
|
+
description: "Notifier targets that receive critical system alerts. Empty = every enabled shared (not personal) target.",
|
|
841
|
+
default: []
|
|
568
842
|
})
|
|
569
843
|
]
|
|
570
844
|
}] });
|
|
571
845
|
}
|
|
572
846
|
async listAlerts(filter) {
|
|
573
|
-
const
|
|
574
|
-
if (
|
|
575
|
-
|
|
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);
|
|
847
|
+
const store = this.alertStore;
|
|
848
|
+
if (store === null) return [];
|
|
849
|
+
return (await store.list(filter)).map(parseAlert);
|
|
588
850
|
}
|
|
589
851
|
async getUnreadCount() {
|
|
590
|
-
const
|
|
591
|
-
if (
|
|
592
|
-
return
|
|
593
|
-
collection: ALERTS_COLLECTION,
|
|
594
|
-
filter: { where: { read: false } }
|
|
595
|
-
});
|
|
852
|
+
const store = this.alertStore;
|
|
853
|
+
if (store === null) return 0;
|
|
854
|
+
return store.countUnread();
|
|
596
855
|
}
|
|
597
856
|
async markRead(alertId) {
|
|
598
857
|
await this.mergeUpdate(alertId, {
|
|
@@ -601,11 +860,11 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
601
860
|
});
|
|
602
861
|
}
|
|
603
862
|
async markAllRead() {
|
|
604
|
-
const
|
|
605
|
-
if (
|
|
606
|
-
const unread = await
|
|
607
|
-
|
|
608
|
-
|
|
863
|
+
const store = this.alertStore;
|
|
864
|
+
if (store === null) return;
|
|
865
|
+
const unread = await store.list({
|
|
866
|
+
unreadOnly: true,
|
|
867
|
+
limit: 1e4
|
|
609
868
|
});
|
|
610
869
|
const now = Date.now();
|
|
611
870
|
for (const record of unread) await this.mergeUpdate(record.id, {
|
|
@@ -702,14 +961,14 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
702
961
|
}
|
|
703
962
|
}
|
|
704
963
|
async readRunnerRecord(alertId) {
|
|
705
|
-
const
|
|
706
|
-
if (
|
|
707
|
-
const raw = await
|
|
708
|
-
|
|
709
|
-
|
|
964
|
+
const store = this.alertStore;
|
|
965
|
+
if (store === null) return null;
|
|
966
|
+
const raw = await store.getData(alertId);
|
|
967
|
+
if (raw === null) return null;
|
|
968
|
+
const alert = AlertSchema.safeParse({
|
|
969
|
+
id: alertId,
|
|
970
|
+
...raw
|
|
710
971
|
});
|
|
711
|
-
if (raw === null || raw === void 0 || typeof raw !== "object") return null;
|
|
712
|
-
const alert = AlertSchema.safeParse(raw);
|
|
713
972
|
if (!alert.success || alert.data.status === "dismissed") return null;
|
|
714
973
|
return parseRunnerRecord(alert.data.metadata?.["runner"]);
|
|
715
974
|
}
|
|
@@ -837,20 +1096,20 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
837
1096
|
});
|
|
838
1097
|
}
|
|
839
1098
|
async readAlertRaw(alertId) {
|
|
840
|
-
const
|
|
841
|
-
if (
|
|
842
|
-
const raw = await
|
|
843
|
-
|
|
844
|
-
key: alertId
|
|
845
|
-
});
|
|
846
|
-
if (raw === null || raw === void 0 || typeof raw !== "object") return null;
|
|
1099
|
+
const store = this.alertStore;
|
|
1100
|
+
if (store === null) return null;
|
|
1101
|
+
const raw = await store.getData(alertId);
|
|
1102
|
+
if (raw === null) return null;
|
|
847
1103
|
const rec = Object.fromEntries(Object.entries(raw));
|
|
848
1104
|
const meta = rec["metadata"];
|
|
849
1105
|
const push = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta["push"] : void 0;
|
|
1106
|
+
const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : void 0;
|
|
850
1107
|
return {
|
|
851
1108
|
...typeof rec["createdAt"] === "number" ? { createdAt: rec["createdAt"] } : {},
|
|
852
1109
|
...typeof rec["read"] === "boolean" ? { read: rec["read"] } : {},
|
|
853
|
-
...
|
|
1110
|
+
...typeof rec["status"] === "string" ? { status: rec["status"] } : {},
|
|
1111
|
+
...isPushState(push) ? { push } : {},
|
|
1112
|
+
...episodeKeyFromMetadata(metadata) !== void 0 ? { episodeKey: episodeKeyFromMetadata(metadata) } : {}
|
|
854
1113
|
};
|
|
855
1114
|
}
|
|
856
1115
|
/** Pushes run one at a time so a burst can never send the same state twice. */
|
|
@@ -861,9 +1120,19 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
861
1120
|
pushPolicy() {
|
|
862
1121
|
return {
|
|
863
1122
|
enabled: this.config.criticalPushEnabled,
|
|
864
|
-
targetIds: this.config.criticalPushTargetIds
|
|
1123
|
+
targetIds: normalizeCriticalPushTargetIds(this.config.criticalPushTargetIds)
|
|
865
1124
|
};
|
|
866
1125
|
}
|
|
1126
|
+
/** Rewrite a legacy CSV `criticalPushTargetIds` string into `string[]`. */
|
|
1127
|
+
async migrateCriticalPushTargetIds() {
|
|
1128
|
+
const raw = this.config.criticalPushTargetIds;
|
|
1129
|
+
if (typeof raw !== "string") return;
|
|
1130
|
+
try {
|
|
1131
|
+
await this.updateGlobalSettings({ criticalPushTargetIds: normalizeCriticalPushTargetIds(raw) });
|
|
1132
|
+
} catch (err) {
|
|
1133
|
+
this.ctx.logger.warn("criticalPushTargetIds CSV migration failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
867
1136
|
pushPorts() {
|
|
868
1137
|
const api = this.ctx.api;
|
|
869
1138
|
return {
|
|
@@ -940,27 +1209,16 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
940
1209
|
return this.pushChain;
|
|
941
1210
|
}
|
|
942
1211
|
async storePushState(alertId, push) {
|
|
943
|
-
const
|
|
944
|
-
if (
|
|
945
|
-
const raw = await
|
|
946
|
-
|
|
947
|
-
|
|
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"];
|
|
1212
|
+
const store = this.alertStore;
|
|
1213
|
+
if (store === null) return;
|
|
1214
|
+
const raw = await store.getData(alertId);
|
|
1215
|
+
if (raw === null) return;
|
|
1216
|
+
const meta = raw["metadata"];
|
|
952
1217
|
const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : {};
|
|
953
|
-
await
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
...existing,
|
|
958
|
-
metadata: {
|
|
959
|
-
...metadata,
|
|
960
|
-
push
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
});
|
|
1218
|
+
await store.mergeUpdate(alertId, { metadata: {
|
|
1219
|
+
...metadata,
|
|
1220
|
+
push
|
|
1221
|
+
} });
|
|
964
1222
|
}
|
|
965
1223
|
/**
|
|
966
1224
|
* Retry every critical alert whose push is still pending - at boot and when
|
|
@@ -968,26 +1226,17 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
968
1226
|
* delivered is skipped by its key, so reconciling never sends twice.
|
|
969
1227
|
*/
|
|
970
1228
|
async reconcilePendingPushes() {
|
|
971
|
-
const
|
|
972
|
-
if (
|
|
1229
|
+
const store = this.alertStore;
|
|
1230
|
+
if (store === null) return;
|
|
973
1231
|
try {
|
|
974
|
-
const rows = await
|
|
975
|
-
collection: ALERTS_COLLECTION,
|
|
976
|
-
filter: {
|
|
977
|
-
orderBy: {
|
|
978
|
-
field: "updatedAt",
|
|
979
|
-
direction: "desc"
|
|
980
|
-
},
|
|
981
|
-
limit: 500
|
|
982
|
-
}
|
|
983
|
-
});
|
|
1232
|
+
const rows = await store.listRecent(500);
|
|
984
1233
|
for (const row of rows) {
|
|
985
1234
|
const parsed = AlertSchema.safeParse({
|
|
986
1235
|
id: row.id,
|
|
987
1236
|
...row.data
|
|
988
1237
|
});
|
|
989
1238
|
if (!parsed.success || parsed.data.status !== "active") continue;
|
|
990
|
-
if (!
|
|
1239
|
+
if (!isCriticalPush(parsed.data)) continue;
|
|
991
1240
|
const push = parsed.data.metadata?.["push"];
|
|
992
1241
|
if (!isPushState(push) || push.state !== "pending") continue;
|
|
993
1242
|
this.pushQueue.set(parsed.data.id, {
|
|
@@ -1007,12 +1256,9 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
1007
1256
|
const modelId = data.modelId ?? "unknown";
|
|
1008
1257
|
const progress = data.progress ?? 0;
|
|
1009
1258
|
const stableId = `model-download:${modelId}`;
|
|
1010
|
-
const
|
|
1011
|
-
if (
|
|
1012
|
-
if (
|
|
1013
|
-
collection: ALERTS_COLLECTION,
|
|
1014
|
-
filter: { where: { id: stableId } }
|
|
1015
|
-
})).length > 0) {
|
|
1259
|
+
const store = this.alertStore;
|
|
1260
|
+
if (store === null) return;
|
|
1261
|
+
if (await store.getData(stableId) !== null) {
|
|
1016
1262
|
const now = Date.now();
|
|
1017
1263
|
if (progress >= 100) {
|
|
1018
1264
|
await this.mergeUpdate(stableId, {
|
|
@@ -1336,8 +1582,29 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
1336
1582
|
}
|
|
1337
1583
|
}
|
|
1338
1584
|
async emitAlert(alert) {
|
|
1339
|
-
await this.
|
|
1340
|
-
|
|
1585
|
+
const existingRaw = await this.readAlertRaw(alert.id);
|
|
1586
|
+
const { alert: toStore, queuePush } = mergeEmitAlert({
|
|
1587
|
+
existing: existingRaw === null ? null : {
|
|
1588
|
+
read: existingRaw.read,
|
|
1589
|
+
episodeKey: existingRaw.episodeKey,
|
|
1590
|
+
status: existingRaw.status
|
|
1591
|
+
},
|
|
1592
|
+
incoming: alert
|
|
1593
|
+
});
|
|
1594
|
+
const stored = alertWithRetainedPush(toStore, existingRaw?.push, existingRaw?.status);
|
|
1595
|
+
const isNew = existingRaw === null;
|
|
1596
|
+
await this.persistAlert(stored);
|
|
1597
|
+
if (isNew) this.emitAlertCreatedEvent(stored);
|
|
1598
|
+
else this.emitAlertUpdatedEvent(alert.id, stored);
|
|
1599
|
+
if (queuePush) {
|
|
1600
|
+
const { key, line } = criticalPushPayload(stored);
|
|
1601
|
+
this.queuePush({
|
|
1602
|
+
alertId: stored.id,
|
|
1603
|
+
key,
|
|
1604
|
+
title: stored.title,
|
|
1605
|
+
line
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1341
1608
|
await this.enforceMaxAlerts();
|
|
1342
1609
|
await this.enforceRetention();
|
|
1343
1610
|
}
|
|
@@ -1353,45 +1620,14 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
1353
1620
|
* so we must read the existing record, merge the patch, and write back.
|
|
1354
1621
|
*/
|
|
1355
1622
|
async mergeUpdate(id, patch) {
|
|
1356
|
-
const
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
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
|
-
});
|
|
1623
|
+
const store = this.alertStore;
|
|
1624
|
+
if (store === null) return;
|
|
1625
|
+
await store.mergeUpdate(id, patch);
|
|
1372
1626
|
}
|
|
1373
1627
|
async persistAlert(alert) {
|
|
1374
|
-
const
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
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
|
-
});
|
|
1628
|
+
const store = this.alertStore;
|
|
1629
|
+
if (store === null) return;
|
|
1630
|
+
await store.persist(alert);
|
|
1395
1631
|
}
|
|
1396
1632
|
emitAlertCreatedEvent(alert) {
|
|
1397
1633
|
this.ctx.eventBus?.emit(createEvent("alert.created", EVENT_SOURCE, {
|
|
@@ -1411,36 +1647,18 @@ var AlertCenterAddon = class extends BaseAddon {
|
|
|
1411
1647
|
}));
|
|
1412
1648
|
}
|
|
1413
1649
|
async enforceMaxAlerts() {
|
|
1414
|
-
const
|
|
1415
|
-
if (
|
|
1416
|
-
if (await
|
|
1417
|
-
const all = await
|
|
1418
|
-
|
|
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
|
-
});
|
|
1650
|
+
const store = this.alertStore;
|
|
1651
|
+
if (store === null) return;
|
|
1652
|
+
if (await store.countAll() <= this.config.maxAlerts) return;
|
|
1653
|
+
const all = await store.listAllByCreatedAtAsc();
|
|
1654
|
+
for (const id of selectOverflow(all.map(toPrunable), this.config.maxAlerts)) await store.delete(id);
|
|
1428
1655
|
}
|
|
1429
1656
|
async enforceRetention() {
|
|
1430
|
-
const
|
|
1431
|
-
if (
|
|
1657
|
+
const store = this.alertStore;
|
|
1658
|
+
if (store === null) return;
|
|
1432
1659
|
const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1e3;
|
|
1433
|
-
const all = await
|
|
1434
|
-
|
|
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
|
-
});
|
|
1660
|
+
const all = await store.listAllByCreatedAtAsc();
|
|
1661
|
+
for (const id of selectExpired(all.map(toPrunable), cutoff)) await store.delete(id);
|
|
1444
1662
|
}
|
|
1445
1663
|
};
|
|
1446
1664
|
//#endregion
|
|
@@ -59,6 +59,10 @@ export interface PushPolicy {
|
|
|
59
59
|
}
|
|
60
60
|
/** Alert categories that are critical system findings. */
|
|
61
61
|
export declare const CRITICAL_CATEGORIES: ReadonlySet<string>;
|
|
62
|
+
export declare function isCriticalPush(alert: {
|
|
63
|
+
readonly severity: string;
|
|
64
|
+
readonly category: string;
|
|
65
|
+
}): boolean;
|
|
62
66
|
export declare function isPushState(value: unknown): value is PushState;
|
|
63
67
|
export declare function selectPushTargets(targets: readonly PushTarget[], policy: PushPolicy): readonly PushTarget[];
|
|
64
68
|
/** One critical finding waiting for its push. */
|