@camstack/system 1.2.457 → 1.2.459

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 (106) hide show
  1. package/dist/addon-runner.js +163 -27
  2. package/dist/addon-runner.mjs +193 -57
  3. package/dist/{agent-https-CoyOZ3pC.js → agent-https-Dnr_nIVx.js} +3 -723
  4. package/dist/{agent-https-CK9Z4sSR.mjs → agent-https-Iw3RSQup.mjs} +4 -616
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +5 -7
  10. package/dist/builtins/alerts/alerts.addon.mjs +5 -7
  11. package/dist/builtins/alerts/record-kinds.d.ts +1 -1
  12. package/dist/builtins/autotrack/index.js +1 -1
  13. package/dist/builtins/autotrack/index.mjs +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +242 -4
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +240 -2
  16. package/dist/builtins/calendars/calendars.addon.js +2 -10
  17. package/dist/builtins/calendars/calendars.addon.mjs +2 -3
  18. package/dist/builtins/calendars/record-kinds.d.ts +1 -1
  19. package/dist/builtins/camera-grid/index.js +1 -1
  20. package/dist/builtins/camera-grid/index.mjs +1 -1
  21. package/dist/builtins/composer/composer.addon.js +2 -2
  22. package/dist/builtins/composer/composer.addon.mjs +2 -2
  23. package/dist/builtins/console-logging/index.js +1 -1
  24. package/dist/builtins/console-logging/index.mjs +1 -1
  25. package/dist/builtins/core-blocks/core-blocks.addon.js +4 -6
  26. package/dist/builtins/core-blocks/core-blocks.addon.mjs +4 -6
  27. package/dist/builtins/device-history/device-history.addon.d.ts +13 -0
  28. package/dist/builtins/device-history/device-history.addon.js +296 -233
  29. package/dist/builtins/device-history/device-history.addon.mjs +296 -233
  30. package/dist/builtins/device-history/ingest/producer-ingest.d.ts +11 -1
  31. package/dist/builtins/device-manager/device-manager.addon.js +2 -4
  32. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -4
  33. package/dist/builtins/hub-forwarder/index.js +1 -1
  34. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  35. package/dist/builtins/keychain/index.js +41 -43
  36. package/dist/builtins/keychain/index.mjs +41 -43
  37. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  38. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  39. package/dist/builtins/local-auth/local-auth.addon.js +24 -40
  40. package/dist/builtins/local-auth/local-auth.addon.mjs +24 -40
  41. package/dist/builtins/local-network/local-network.addon.js +2 -2
  42. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  43. package/dist/builtins/loki-logging/index.js +1 -1
  44. package/dist/builtins/loki-logging/index.mjs +1 -1
  45. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  46. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  47. package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +1 -2
  48. package/dist/builtins/platform-probe/coral-accelerators.d.ts +26 -9
  49. package/dist/builtins/platform-probe/index.js +11 -68
  50. package/dist/builtins/platform-probe/index.mjs +11 -68
  51. package/dist/builtins/record-entries/index.js +1 -1
  52. package/dist/builtins/record-entries/index.mjs +1 -1
  53. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  54. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  55. package/dist/builtins/snapshot/index.js +1 -1
  56. package/dist/builtins/snapshot/index.mjs +1 -1
  57. package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +0 -15
  58. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  59. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  60. package/dist/builtins/sqlite-storage/index.js +1 -1
  61. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  62. package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +0 -44
  63. package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +0 -2
  64. package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +0 -21
  65. package/dist/builtins/sqlite-storage/records/records-engine.d.ts +3 -20
  66. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +4 -18
  67. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +1 -1
  68. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -17
  69. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +21 -196
  70. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +21 -196
  71. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +6 -14
  72. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -2
  73. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +7 -9
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +7 -9
  75. package/dist/builtins/system-config/system-config.addon.js +667 -40
  76. package/dist/builtins/system-config/system-config.addon.mjs +625 -15
  77. package/dist/builtins/winston-logging/index.js +1 -1
  78. package/dist/builtins/winston-logging/index.mjs +1 -1
  79. package/dist/{composition-sources-B_jeZDRJ.mjs → composition-sources-DNRZWR1j.mjs} +1 -1
  80. package/dist/{composition-sources-qKyvMAvc.js → composition-sources-b0e_2I-D.js} +1 -1
  81. package/dist/{constants-B_X9cWEK.js → constants-6OeJiZgi.js} +1 -1
  82. package/dist/{constants-cxKcZRMi.mjs → constants-BnkOdj9Q.mjs} +1 -1
  83. package/dist/coral-accelerators-Bi_c3Rft.js +175 -0
  84. package/dist/coral-accelerators-DcnZvctM.mjs +162 -0
  85. package/dist/{device-ca-BB6nHAL5.mjs → device-ca-Bnkw8GyU.mjs} +1 -1
  86. package/dist/{device-ca-CVK3YcR_.js → device-ca-CPTDs--d.js} +1 -1
  87. package/dist/{dist-C89nqNnn.js → dist-Bn-RNanh.js} +84 -140
  88. package/dist/{dist-Dhux90yB.mjs → dist-Wy8cTxg6.mjs} +85 -123
  89. package/dist/file-host-worker.js +1 -1
  90. package/dist/file-host-worker.mjs +1 -1
  91. package/dist/{hub-mdns-ciao-B8olZqqd.mjs → hub-mdns-ciao-CJu0nhla.mjs} +2 -2
  92. package/dist/{hub-mdns-ciao-DB1Y9agt.js → hub-mdns-ciao-CTBTlia4.js} +2 -2
  93. package/dist/index.js +32 -58
  94. package/dist/index.mjs +16 -42
  95. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +7 -3
  96. package/dist/{restore-archive-DyOaPeAr.mjs → restore-archive-CmP-iiG9.mjs} +84 -331
  97. package/dist/{restore-archive-4DOUR5Gu.js → restore-archive-DM1OBYq4.js} +89 -342
  98. package/dist/{wal-maintenance-DVN-DiVP.js → wal-maintenance-DUHEp_09.js} +0 -0
  99. package/dist/{wal-maintenance-BMiX6UIa.mjs → wal-maintenance-NKbwWovZ.mjs} +0 -0
  100. package/package.json +1 -1
  101. package/dist/builtins/records/legacy-table-row-count.d.ts +0 -5
  102. package/dist/builtins/records/phase6-declare-gate.d.ts +0 -28
  103. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +0 -5
  104. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +0 -6
  105. package/dist/phase6-declare-gate-BO-_jLh_.js +0 -98
  106. package/dist/phase6-declare-gate-x9ZCbQJP.mjs +0 -93
@@ -3,9 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-C89nqNnn.js");
6
+ const require_dist = require("../../dist-Bn-RNanh.js");
7
7
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
- const require_phase6_declare_gate = require("../../phase6-declare-gate-BO-_jLh_.js");
9
8
  //#region src/builtins/alerts/alert-episode-policy.ts
10
9
  /**
11
10
  * When does an alert open a new EPISODE, and which edge of it is announced?
@@ -225,7 +224,7 @@ var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
225
224
  /**
226
225
  * Record kinds owned by alert-center (records plan phase 4).
227
226
  */
228
- /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
227
+ /** The legacy collection the kind replaced (canonical KV before phase 4); read only without records. */
229
228
  var ALERTS_COLLECTION = "alerts";
230
229
  var AlertBodySchema = require_dist.AlertSchema.omit({ id: true });
231
230
  var _alertCenterRecordKinds = require_dist.defineRecordKinds({ alerts: {
@@ -251,8 +250,7 @@ var _alertCenterRecordKinds = require_dist.defineRecordKinds({ alerts: {
251
250
  retention: {
252
251
  owner: "alert-center",
253
252
  reason: "maxAlerts cap and retentionDays enforced on write (enforceMaxAlerts / enforceRetention); read alerts preferred when trimming overflow"
254
- },
255
- adoptsFrom: ALERTS_COLLECTION
253
+ }
256
254
  } });
257
255
  var alertCenterRecordKinds = _alertCenterRecordKinds;
258
256
  /** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
@@ -644,8 +642,8 @@ var AlertCenterAddon = class extends require_dist.BaseAddon {
644
642
  async onInitialize() {
645
643
  const records = this.ctx.records;
646
644
  const store = this.ctx.api?.settingsStore;
647
- const useRecords = records !== void 0 && store !== void 0 && await require_phase6_declare_gate.resolvePhase6UseRecordsPathForHub(this.ctx, "alert-center", alertCenterRecordKinds, ["alerts"]);
648
- this.alertStore = useRecords && records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
645
+ if (records !== void 0) await records.declare(alertCenterRecordKinds);
646
+ this.alertStore = records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
649
647
  if (this.alertStore === null) throw new Error("alert-center needs ctx.records or settings-store on the hub");
650
648
  const alertsProvider = {
651
649
  emit: (alert) => this.emitAlert(alert),
@@ -1,6 +1,5 @@
1
- import { Ct as alertEpisodePayload, Hi as createEvent, Ki as defineRecordKinds, Oa as EventCategory, Sn as isAlertEpisodeSeverity, St as alertEpisodeId, i as AlertSchema, ni as BaseAddon, ti as errMsg, wt as alertsCapability, xn as isAlertEpisodeOpen } from "../../dist-Dhux90yB.mjs";
1
+ import { Ct as alertEpisodePayload, Gi as defineRecordKinds, Hi as createEvent, Sn as isAlertEpisodeSeverity, St as alertEpisodeId, Ta as EventCategory, i as AlertSchema, ni as BaseAddon, ti as errMsg, wt as alertsCapability, xn as isAlertEpisodeOpen } from "../../dist-Wy8cTxg6.mjs";
2
2
  import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
3
- import { t as resolvePhase6UseRecordsPathForHub } from "../../phase6-declare-gate-x9ZCbQJP.mjs";
4
3
  //#region src/builtins/alerts/alert-episode-policy.ts
5
4
  /**
6
5
  * When does an alert open a new EPISODE, and which edge of it is announced?
@@ -220,7 +219,7 @@ var import_read_all_rows = require_read_all_rows();
220
219
  /**
221
220
  * Record kinds owned by alert-center (records plan phase 4).
222
221
  */
223
- /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
222
+ /** The legacy collection the kind replaced (canonical KV before phase 4); read only without records. */
224
223
  var ALERTS_COLLECTION = "alerts";
225
224
  var _alertCenterRecordKinds = defineRecordKinds({ alerts: {
226
225
  schema: AlertSchema.omit({ id: true }),
@@ -245,8 +244,7 @@ var _alertCenterRecordKinds = defineRecordKinds({ alerts: {
245
244
  retention: {
246
245
  owner: "alert-center",
247
246
  reason: "maxAlerts cap and retentionDays enforced on write (enforceMaxAlerts / enforceRetention); read alerts preferred when trimming overflow"
248
- },
249
- adoptsFrom: ALERTS_COLLECTION
247
+ }
250
248
  } });
251
249
  var alertCenterRecordKinds = _alertCenterRecordKinds;
252
250
  /** Narrow kind for `records.kind()` — `IsolatedRecordKinds` string index is `| undefined`. */
@@ -638,8 +636,8 @@ var AlertCenterAddon = class extends BaseAddon {
638
636
  async onInitialize() {
639
637
  const records = this.ctx.records;
640
638
  const store = this.ctx.api?.settingsStore;
641
- const useRecords = records !== void 0 && store !== void 0 && await resolvePhase6UseRecordsPathForHub(this.ctx, "alert-center", alertCenterRecordKinds, ["alerts"]);
642
- this.alertStore = useRecords && records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
639
+ if (records !== void 0) await records.declare(alertCenterRecordKinds);
640
+ this.alertStore = records !== void 0 ? AlertStore.of(records) : store === void 0 ? null : AlertStore.legacy(store);
643
641
  if (this.alertStore === null) throw new Error("alert-center needs ctx.records or settings-store on the hub");
644
642
  const alertsProvider = {
645
643
  emit: (alert) => this.emitAlert(alert),
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { type Alert, type DefinedRecordKind } from "@camstack/types";
5
5
  import { z } from "zod";
6
- /** Legacy collection / adoptsFrom target (canonical KV before phase 4). */
6
+ /** The legacy collection the kind replaced (canonical KV before phase 4); read only without records. */
7
7
  export declare const ALERTS_COLLECTION = "alerts";
8
8
  export type AlertBody = Omit<Alert, "id">;
9
9
  export declare const AlertBodySchema: 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-C89nqNnn.js");
6
+ const require_dist = require("../../dist-Bn-RNanh.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 isEvent, L as FIRST_LEVEL_MACRO_CLASSES, Oa as EventCategory, Ot as bareAddonId, ni as BaseAddon, rr as ptzAutotrackCapability, ti as errMsg } from "../../dist-Dhux90yB.mjs";
1
+ import { L as FIRST_LEVEL_MACRO_CLASSES, Ot as bareAddonId, Qi as isEvent, Ta as EventCategory, ni as BaseAddon, rr as ptzAutotrackCapability, ti as errMsg } from "../../dist-Wy8cTxg6.mjs";
2
2
  //#region src/builtins/autotrack/autotrack-config.ts
3
3
  var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
4
4
  deadZoneFraction: .5,
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-C89nqNnn.js");
6
+ const require_dist = require("../../dist-Bn-RNanh.js");
7
7
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
- const require_restore_archive = require("../../restore-archive-4DOUR5Gu.js");
8
+ const require_restore_archive = require("../../restore-archive-DM1OBYq4.js");
9
9
  let node_crypto = require("node:crypto");
10
10
  let node_fs_promises = require("node:fs/promises");
11
11
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -85,6 +85,81 @@ async function seedWeeklySchedule(store, markers) {
85
85
  return seed;
86
86
  }
87
87
  //#endregion
88
+ //#region src/builtins/backup-orchestrator/seed-marker-store.ts
89
+ /**
90
+ * @durable class=config owner=backup-orchestrator
91
+ * write="the orchestrator inserts one row per seed id the first time that
92
+ * seed is created (or found already created); never updated"
93
+ * retention="none — one tiny row per seed ever made; deleting it lets the
94
+ * seed be re-created once more on the next boot"
95
+ */
96
+ var BACKUP_SEED_MARKERS_COLLECTION = "backup_seed_markers";
97
+ var COLUMNS$1 = [{
98
+ name: "seed_id",
99
+ type: "TEXT",
100
+ primaryKey: true
101
+ }, {
102
+ name: "seeded_at",
103
+ type: "INTEGER",
104
+ notNull: true
105
+ }];
106
+ var BackupSeedMarkerStore = class {
107
+ store;
108
+ now;
109
+ declared = false;
110
+ markersKind;
111
+ constructor(store, now = Date.now, markersKind = null) {
112
+ this.store = store;
113
+ this.now = now;
114
+ this.markersKind = markersKind;
115
+ }
116
+ async ensureDeclared() {
117
+ if (this.markersKind !== null) return;
118
+ if (this.declared) return;
119
+ await this.store.declareCollection({
120
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
121
+ columns: COLUMNS$1
122
+ });
123
+ this.declared = true;
124
+ }
125
+ async has(seedId) {
126
+ await this.ensureDeclared();
127
+ const kind = this.markersKind;
128
+ if (kind !== null) return await kind.get(seedId) !== null;
129
+ return (await this.store.query({
130
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
131
+ filter: {
132
+ where: { seed_id: seedId },
133
+ limit: 1
134
+ }
135
+ })).length > 0;
136
+ }
137
+ async mark(seedId) {
138
+ await this.ensureDeclared();
139
+ if (await this.has(seedId)) return;
140
+ const kind = this.markersKind;
141
+ if (kind !== null) {
142
+ const body = { seededAt: this.now() };
143
+ const data = require_restore_archive.backupOrchestratorRecordKinds["seed-markers"].schema.parse(body);
144
+ await kind.put({
145
+ id: seedId,
146
+ data
147
+ });
148
+ return;
149
+ }
150
+ await this.store.insert({
151
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
152
+ record: {
153
+ id: seedId,
154
+ data: {
155
+ seed_id: seedId,
156
+ seeded_at: this.now()
157
+ }
158
+ }
159
+ });
160
+ }
161
+ };
162
+ //#endregion
88
163
  //#region ../../node_modules/croner/dist/croner.js
89
164
  function T(s) {
90
165
  return Date.UTC(s.y, s.m - 1, s.d, s.h, s.i, s.s);
@@ -1209,6 +1284,169 @@ async function downloadArchiveToCache(input) {
1209
1284
  }
1210
1285
  }
1211
1286
  //#endregion
1287
+ //#region src/builtins/backup-orchestrator/encryption-key-store.ts
1288
+ /**
1289
+ * @durable class=config owner=backup-orchestrator
1290
+ * write="`setupEncryption` inserts one row per generated key and retires the
1291
+ * previous active row; `disableEncryption` retires the active row"
1292
+ * retention="none — one small row per key ever generated; a retired row
1293
+ * names the key older archives need"
1294
+ */
1295
+ var BACKUP_ENCRYPTION_KEYS_COLLECTION = "backup_encryption_keys";
1296
+ var COLUMNS = [
1297
+ {
1298
+ name: "key_id",
1299
+ type: "TEXT",
1300
+ primaryKey: true
1301
+ },
1302
+ {
1303
+ name: "public_key",
1304
+ type: "TEXT",
1305
+ notNull: true
1306
+ },
1307
+ {
1308
+ name: "created_at",
1309
+ type: "INTEGER",
1310
+ notNull: true
1311
+ },
1312
+ {
1313
+ name: "retired_at",
1314
+ type: "INTEGER"
1315
+ }
1316
+ ];
1317
+ var BackupEncryptionKeyStore = class {
1318
+ store;
1319
+ now;
1320
+ declared = false;
1321
+ keysKind;
1322
+ constructor(store, now = Date.now, keysKind = null) {
1323
+ this.store = store;
1324
+ this.now = now;
1325
+ this.keysKind = keysKind;
1326
+ }
1327
+ async ensureDeclared() {
1328
+ if (this.keysKind !== null) return;
1329
+ if (this.declared) return;
1330
+ await this.store.declareCollection({
1331
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1332
+ columns: COLUMNS
1333
+ });
1334
+ this.declared = true;
1335
+ }
1336
+ /** Every key, newest first. */
1337
+ async list() {
1338
+ await this.ensureDeclared();
1339
+ const kind = this.keysKind;
1340
+ if (kind !== null) {
1341
+ const rows = await (0, import_read_all_rows.readAllRows)(kind);
1342
+ rows.sort((a, b) => b.data.createdAt - a.data.createdAt);
1343
+ const out = [];
1344
+ for (const row of rows) {
1345
+ const record = bodyToRecord(row.id, row.data);
1346
+ if (record !== null) out.push(record);
1347
+ }
1348
+ return out;
1349
+ }
1350
+ const rows = await this.store.query({
1351
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1352
+ filter: { orderBy: {
1353
+ field: "created_at",
1354
+ direction: "desc"
1355
+ } }
1356
+ });
1357
+ const out = [];
1358
+ for (const row of rows) {
1359
+ const record = toRecord(row.data);
1360
+ if (record !== null) out.push(record);
1361
+ }
1362
+ return out;
1363
+ }
1364
+ /** The key new archives are encrypted to; `null` = encryption off. */
1365
+ async active() {
1366
+ return (await this.list()).find((k) => k.retiredAt === null) ?? null;
1367
+ }
1368
+ /** Make `publicKey` the active key; the previous one is retired, kept listed. */
1369
+ async activate(input) {
1370
+ const parsed = require_restore_archive.parseBackupPublicKey(input.publicKey);
1371
+ const t = this.now();
1372
+ await this.retireActive(t);
1373
+ const record = {
1374
+ keyId: parsed.keyId,
1375
+ publicKey: input.publicKey.trim(),
1376
+ createdAt: t,
1377
+ retiredAt: null
1378
+ };
1379
+ await this.write(record);
1380
+ return record;
1381
+ }
1382
+ /** Encryption off: the active key is retired. Archives already made keep needing it. */
1383
+ async disable() {
1384
+ await this.retireActive(this.now());
1385
+ }
1386
+ async retireActive(at) {
1387
+ for (const key of await this.list()) if (key.retiredAt === null) await this.write({
1388
+ ...key,
1389
+ retiredAt: at
1390
+ });
1391
+ }
1392
+ async write(record) {
1393
+ await this.ensureDeclared();
1394
+ const kind = this.keysKind;
1395
+ if (kind !== null) {
1396
+ const body = {
1397
+ keyId: record.keyId,
1398
+ publicKey: record.publicKey,
1399
+ createdAt: record.createdAt,
1400
+ retiredAt: record.retiredAt
1401
+ };
1402
+ const data = require_restore_archive.backupOrchestratorRecordKinds["encryption-keys"].schema.parse(body);
1403
+ await kind.put({
1404
+ id: record.keyId,
1405
+ data
1406
+ });
1407
+ return;
1408
+ }
1409
+ await this.store.deleteWhere({
1410
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1411
+ filter: { where: { key_id: record.keyId } }
1412
+ });
1413
+ await this.store.insert({
1414
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1415
+ record: {
1416
+ id: record.keyId,
1417
+ data: {
1418
+ key_id: record.keyId,
1419
+ public_key: record.publicKey,
1420
+ created_at: record.createdAt,
1421
+ retired_at: record.retiredAt
1422
+ }
1423
+ }
1424
+ });
1425
+ }
1426
+ };
1427
+ function bodyToRecord(keyId, body) {
1428
+ if (!keyId) return null;
1429
+ return {
1430
+ keyId: body.keyId,
1431
+ publicKey: body.publicKey,
1432
+ createdAt: body.createdAt,
1433
+ retiredAt: body.retiredAt
1434
+ };
1435
+ }
1436
+ function toRecord(row) {
1437
+ const keyId = row["key_id"];
1438
+ const publicKey = row["public_key"];
1439
+ const createdAt = row["created_at"];
1440
+ if (typeof keyId !== "string" || typeof publicKey !== "string") return null;
1441
+ const retired = row["retired_at"];
1442
+ return {
1443
+ keyId,
1444
+ publicKey,
1445
+ createdAt: typeof createdAt === "number" ? createdAt : Number(createdAt ?? 0),
1446
+ retiredAt: typeof retired === "number" ? retired : null
1447
+ };
1448
+ }
1449
+ //#endregion
1212
1450
  //#region src/builtins/backup-orchestrator/manifest-store.ts
1213
1451
  /** File path (relative to the location root) where the index lives. */
1214
1452
  var MANIFESTS_FILENAME = "manifests.json";
@@ -2194,7 +2432,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
2194
2432
  }
2195
2433
  await this.seedWeekly();
2196
2434
  const settingsStore = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
2197
- this.encryptionKeys = settingsStore ? new require_restore_archive.BackupEncryptionKeyStore(settingsStore, Date.now, this.backupRecords?.encryptionKeys ?? null) : null;
2435
+ this.encryptionKeys = settingsStore ? new BackupEncryptionKeyStore(settingsStore, Date.now, this.backupRecords?.encryptionKeys ?? null) : null;
2198
2436
  const provider = {
2199
2437
  listDestinations: () => this.listDestinations(),
2200
2438
  list: () => this.aggregatedList(),
@@ -3197,7 +3435,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
3197
3435
  try {
3198
3436
  const store = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
3199
3437
  if (!store) return;
3200
- const seed = await seedWeeklySchedule(this.schedules, new require_restore_archive.BackupSeedMarkerStore(store, Date.now, this.backupRecords?.seedMarkers ?? null));
3438
+ const seed = await seedWeeklySchedule(this.schedules, new BackupSeedMarkerStore(store, Date.now, this.backupRecords?.seedMarkers ?? null));
3201
3439
  if (seed === null) return;
3202
3440
  this.ctx.logger.info("backup: seeded the weekly events & history schedule", { meta: {
3203
3441
  scheduleId: seed.id,
@@ -1,6 +1,6 @@
1
- import { Ca as toNodeId, Dt as backupCapability, Oa as EventCategory, Or as storageOccupancyCapability, Un as mayWriteToLocation, ni as BaseAddon, sa as nodePin } from "../../dist-Dhux90yB.mjs";
1
+ import { Dt as backupCapability, Or as storageOccupancyCapability, Ta as EventCategory, Un as mayWriteToLocation, ba as toNodeId, ni as BaseAddon, oa as nodePin } from "../../dist-Wy8cTxg6.mjs";
2
2
  import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
3
- import { _ as parseBackupSecretKey, a as BackupSnapshotRefusedError, c as backupOrchestratorRecordKinds, d as BackupEncryptionKeyStore, g as generateBackupKeyPair, h as ENCRYPTED_BACKUP_SUFFIX, i as BackupCancelledError, l as backupRecordStoresOf, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as BackupKeyFormatError, r as prepareRestoreArchive, s as SystemBackupService, u as BackupSeedMarkerStore } from "../../restore-archive-DyOaPeAr.mjs";
3
+ import { _ as backupRecordStoresOf, a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, g as backupOrchestratorRecordKinds, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-CmP-iiG9.mjs";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import * as fsp from "node:fs/promises";
6
6
  import * as path$1 from "node:path";
@@ -77,6 +77,81 @@ async function seedWeeklySchedule(store, markers) {
77
77
  return seed;
78
78
  }
79
79
  //#endregion
80
+ //#region src/builtins/backup-orchestrator/seed-marker-store.ts
81
+ /**
82
+ * @durable class=config owner=backup-orchestrator
83
+ * write="the orchestrator inserts one row per seed id the first time that
84
+ * seed is created (or found already created); never updated"
85
+ * retention="none — one tiny row per seed ever made; deleting it lets the
86
+ * seed be re-created once more on the next boot"
87
+ */
88
+ var BACKUP_SEED_MARKERS_COLLECTION = "backup_seed_markers";
89
+ var COLUMNS$1 = [{
90
+ name: "seed_id",
91
+ type: "TEXT",
92
+ primaryKey: true
93
+ }, {
94
+ name: "seeded_at",
95
+ type: "INTEGER",
96
+ notNull: true
97
+ }];
98
+ var BackupSeedMarkerStore = class {
99
+ store;
100
+ now;
101
+ declared = false;
102
+ markersKind;
103
+ constructor(store, now = Date.now, markersKind = null) {
104
+ this.store = store;
105
+ this.now = now;
106
+ this.markersKind = markersKind;
107
+ }
108
+ async ensureDeclared() {
109
+ if (this.markersKind !== null) return;
110
+ if (this.declared) return;
111
+ await this.store.declareCollection({
112
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
113
+ columns: COLUMNS$1
114
+ });
115
+ this.declared = true;
116
+ }
117
+ async has(seedId) {
118
+ await this.ensureDeclared();
119
+ const kind = this.markersKind;
120
+ if (kind !== null) return await kind.get(seedId) !== null;
121
+ return (await this.store.query({
122
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
123
+ filter: {
124
+ where: { seed_id: seedId },
125
+ limit: 1
126
+ }
127
+ })).length > 0;
128
+ }
129
+ async mark(seedId) {
130
+ await this.ensureDeclared();
131
+ if (await this.has(seedId)) return;
132
+ const kind = this.markersKind;
133
+ if (kind !== null) {
134
+ const body = { seededAt: this.now() };
135
+ const data = backupOrchestratorRecordKinds["seed-markers"].schema.parse(body);
136
+ await kind.put({
137
+ id: seedId,
138
+ data
139
+ });
140
+ return;
141
+ }
142
+ await this.store.insert({
143
+ collection: BACKUP_SEED_MARKERS_COLLECTION,
144
+ record: {
145
+ id: seedId,
146
+ data: {
147
+ seed_id: seedId,
148
+ seeded_at: this.now()
149
+ }
150
+ }
151
+ });
152
+ }
153
+ };
154
+ //#endregion
80
155
  //#region ../../node_modules/croner/dist/croner.js
81
156
  function T(s) {
82
157
  return Date.UTC(s.y, s.m - 1, s.d, s.h, s.i, s.s);
@@ -1201,6 +1276,169 @@ async function downloadArchiveToCache(input) {
1201
1276
  }
1202
1277
  }
1203
1278
  //#endregion
1279
+ //#region src/builtins/backup-orchestrator/encryption-key-store.ts
1280
+ /**
1281
+ * @durable class=config owner=backup-orchestrator
1282
+ * write="`setupEncryption` inserts one row per generated key and retires the
1283
+ * previous active row; `disableEncryption` retires the active row"
1284
+ * retention="none — one small row per key ever generated; a retired row
1285
+ * names the key older archives need"
1286
+ */
1287
+ var BACKUP_ENCRYPTION_KEYS_COLLECTION = "backup_encryption_keys";
1288
+ var COLUMNS = [
1289
+ {
1290
+ name: "key_id",
1291
+ type: "TEXT",
1292
+ primaryKey: true
1293
+ },
1294
+ {
1295
+ name: "public_key",
1296
+ type: "TEXT",
1297
+ notNull: true
1298
+ },
1299
+ {
1300
+ name: "created_at",
1301
+ type: "INTEGER",
1302
+ notNull: true
1303
+ },
1304
+ {
1305
+ name: "retired_at",
1306
+ type: "INTEGER"
1307
+ }
1308
+ ];
1309
+ var BackupEncryptionKeyStore = class {
1310
+ store;
1311
+ now;
1312
+ declared = false;
1313
+ keysKind;
1314
+ constructor(store, now = Date.now, keysKind = null) {
1315
+ this.store = store;
1316
+ this.now = now;
1317
+ this.keysKind = keysKind;
1318
+ }
1319
+ async ensureDeclared() {
1320
+ if (this.keysKind !== null) return;
1321
+ if (this.declared) return;
1322
+ await this.store.declareCollection({
1323
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1324
+ columns: COLUMNS
1325
+ });
1326
+ this.declared = true;
1327
+ }
1328
+ /** Every key, newest first. */
1329
+ async list() {
1330
+ await this.ensureDeclared();
1331
+ const kind = this.keysKind;
1332
+ if (kind !== null) {
1333
+ const rows = await (0, import_read_all_rows.readAllRows)(kind);
1334
+ rows.sort((a, b) => b.data.createdAt - a.data.createdAt);
1335
+ const out = [];
1336
+ for (const row of rows) {
1337
+ const record = bodyToRecord(row.id, row.data);
1338
+ if (record !== null) out.push(record);
1339
+ }
1340
+ return out;
1341
+ }
1342
+ const rows = await this.store.query({
1343
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1344
+ filter: { orderBy: {
1345
+ field: "created_at",
1346
+ direction: "desc"
1347
+ } }
1348
+ });
1349
+ const out = [];
1350
+ for (const row of rows) {
1351
+ const record = toRecord(row.data);
1352
+ if (record !== null) out.push(record);
1353
+ }
1354
+ return out;
1355
+ }
1356
+ /** The key new archives are encrypted to; `null` = encryption off. */
1357
+ async active() {
1358
+ return (await this.list()).find((k) => k.retiredAt === null) ?? null;
1359
+ }
1360
+ /** Make `publicKey` the active key; the previous one is retired, kept listed. */
1361
+ async activate(input) {
1362
+ const parsed = parseBackupPublicKey(input.publicKey);
1363
+ const t = this.now();
1364
+ await this.retireActive(t);
1365
+ const record = {
1366
+ keyId: parsed.keyId,
1367
+ publicKey: input.publicKey.trim(),
1368
+ createdAt: t,
1369
+ retiredAt: null
1370
+ };
1371
+ await this.write(record);
1372
+ return record;
1373
+ }
1374
+ /** Encryption off: the active key is retired. Archives already made keep needing it. */
1375
+ async disable() {
1376
+ await this.retireActive(this.now());
1377
+ }
1378
+ async retireActive(at) {
1379
+ for (const key of await this.list()) if (key.retiredAt === null) await this.write({
1380
+ ...key,
1381
+ retiredAt: at
1382
+ });
1383
+ }
1384
+ async write(record) {
1385
+ await this.ensureDeclared();
1386
+ const kind = this.keysKind;
1387
+ if (kind !== null) {
1388
+ const body = {
1389
+ keyId: record.keyId,
1390
+ publicKey: record.publicKey,
1391
+ createdAt: record.createdAt,
1392
+ retiredAt: record.retiredAt
1393
+ };
1394
+ const data = backupOrchestratorRecordKinds["encryption-keys"].schema.parse(body);
1395
+ await kind.put({
1396
+ id: record.keyId,
1397
+ data
1398
+ });
1399
+ return;
1400
+ }
1401
+ await this.store.deleteWhere({
1402
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1403
+ filter: { where: { key_id: record.keyId } }
1404
+ });
1405
+ await this.store.insert({
1406
+ collection: BACKUP_ENCRYPTION_KEYS_COLLECTION,
1407
+ record: {
1408
+ id: record.keyId,
1409
+ data: {
1410
+ key_id: record.keyId,
1411
+ public_key: record.publicKey,
1412
+ created_at: record.createdAt,
1413
+ retired_at: record.retiredAt
1414
+ }
1415
+ }
1416
+ });
1417
+ }
1418
+ };
1419
+ function bodyToRecord(keyId, body) {
1420
+ if (!keyId) return null;
1421
+ return {
1422
+ keyId: body.keyId,
1423
+ publicKey: body.publicKey,
1424
+ createdAt: body.createdAt,
1425
+ retiredAt: body.retiredAt
1426
+ };
1427
+ }
1428
+ function toRecord(row) {
1429
+ const keyId = row["key_id"];
1430
+ const publicKey = row["public_key"];
1431
+ const createdAt = row["created_at"];
1432
+ if (typeof keyId !== "string" || typeof publicKey !== "string") return null;
1433
+ const retired = row["retired_at"];
1434
+ return {
1435
+ keyId,
1436
+ publicKey,
1437
+ createdAt: typeof createdAt === "number" ? createdAt : Number(createdAt ?? 0),
1438
+ retiredAt: typeof retired === "number" ? retired : null
1439
+ };
1440
+ }
1441
+ //#endregion
1204
1442
  //#region src/builtins/backup-orchestrator/manifest-store.ts
1205
1443
  /** File path (relative to the location root) where the index lives. */
1206
1444
  var MANIFESTS_FILENAME = "manifests.json";
@@ -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-C89nqNnn.js");
6
+ const require_dist = require("../../dist-Bn-RNanh.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let zod = require("zod");
9
9
  //#region src/builtins/calendars/calendar-color.ts
@@ -31,13 +31,6 @@ function defaultCalendarColor(calendarId) {
31
31
  }
32
32
  return CALENDAR_COLOR_PALETTE[Math.abs(hash) % CALENDAR_COLOR_PALETTE.length];
33
33
  }
34
- //#endregion
35
- //#region src/builtins/calendars/record-kinds.ts
36
- /**
37
- * Record kinds owned by calendars (phase 4).
38
- */
39
- /** Legacy collection / adoptsFrom target. */
40
- var CALENDARS_USER_PREFS_COLLECTION = "calendars:user-prefs";
41
34
  var CalendarUserPrefsBodySchema = zod.z.object({
42
35
  calendars: require_dist.CalendarPreferencesSchema.shape.calendars,
43
36
  updatedAt: zod.z.number()
@@ -52,8 +45,7 @@ var _calendarsRecordKinds = require_dist.defineRecordKinds({ "user-prefs": {
52
45
  name: "updated_at",
53
46
  fields: ["updatedAt"]
54
47
  }],
55
- retention: { none: "a missing row reads as empty prefs (all visible, system colours)" },
56
- adoptsFrom: CALENDARS_USER_PREFS_COLLECTION
48
+ retention: { none: "a missing row reads as empty prefs (all visible, system colours)" }
57
49
  } });
58
50
  var calendarsRecordKinds = _calendarsRecordKinds;
59
51
  _calendarsRecordKinds["user-prefs"];