@camstack/system 1.2.460 → 1.2.462

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 (108) hide show
  1. package/dist/addon-runner.js +21 -276
  2. package/dist/addon-runner.mjs +21 -276
  3. package/dist/addon-utils.js +1 -1
  4. package/dist/addon-utils.mjs +1 -1
  5. package/dist/{agent-https-Dnr_nIVx.js → agent-https-C6M6apPV.js} +1 -1
  6. package/dist/{agent-https-Iw3RSQup.mjs → agent-https-CC7jpktS.mjs} +1 -1
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  10. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  11. package/dist/builtins/alerts/alerts.addon.js +1 -1
  12. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  13. package/dist/builtins/autotrack/index.js +1 -1
  14. package/dist/builtins/autotrack/index.mjs +1 -1
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -3
  16. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +51 -502
  17. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +51 -502
  18. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +5 -21
  19. package/dist/builtins/backup-orchestrator/record-kinds.d.ts +0 -2
  20. package/dist/builtins/backup-orchestrator/schedule-store.d.ts +5 -13
  21. package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +9 -19
  22. package/dist/builtins/calendars/calendars.addon.js +1 -1
  23. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  24. package/dist/builtins/camera-grid/index.js +1 -1
  25. package/dist/builtins/camera-grid/index.mjs +1 -1
  26. package/dist/builtins/cluster-agent/record-kinds.d.ts +0 -1
  27. package/dist/builtins/composer/composer.addon.js +2 -2
  28. package/dist/builtins/composer/composer.addon.mjs +2 -2
  29. package/dist/builtins/console-logging/index.js +1 -1
  30. package/dist/builtins/console-logging/index.mjs +1 -1
  31. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  32. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  33. package/dist/builtins/device-history/device-history.addon.js +1 -1
  34. package/dist/builtins/device-history/device-history.addon.mjs +1 -1
  35. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  36. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  37. package/dist/builtins/hub-forwarder/index.js +1 -1
  38. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  39. package/dist/builtins/keychain/index.js +3 -3
  40. package/dist/builtins/keychain/index.mjs +3 -3
  41. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  42. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  43. package/dist/builtins/local-auth/auth-schema.d.ts +2 -12
  44. package/dist/builtins/local-auth/local-auth.addon.js +52 -191
  45. package/dist/builtins/local-auth/local-auth.addon.mjs +52 -191
  46. package/dist/builtins/local-auth/oauth-session-manager.d.ts +13 -4
  47. package/dist/builtins/local-auth/record-kinds.d.ts +1 -1
  48. package/dist/builtins/local-network/local-network.addon.js +2 -2
  49. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  50. package/dist/builtins/loki-logging/index.js +1 -1
  51. package/dist/builtins/loki-logging/index.mjs +1 -1
  52. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  53. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  54. package/dist/builtins/platform-probe/index.js +1 -1
  55. package/dist/builtins/platform-probe/index.mjs +1 -1
  56. package/dist/builtins/record-entries/index.js +1 -1
  57. package/dist/builtins/record-entries/index.mjs +1 -1
  58. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  59. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  60. package/dist/builtins/snapshot/index.js +1 -1
  61. package/dist/builtins/snapshot/index.mjs +1 -1
  62. package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +0 -9
  63. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  64. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  65. package/dist/builtins/sqlite-storage/index.js +1 -1
  66. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  67. package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +0 -8
  68. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +0 -2
  69. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -28
  70. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +1 -2
  71. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +6 -170
  72. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +6 -170
  73. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +3 -17
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  75. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  76. package/dist/builtins/system-config/system-config.addon.js +3 -3
  77. package/dist/builtins/system-config/system-config.addon.mjs +280 -280
  78. package/dist/builtins/winston-logging/index.js +1 -1
  79. package/dist/builtins/winston-logging/index.mjs +1 -1
  80. package/dist/{composition-sources-b0e_2I-D.js → composition-sources-BPnpB9XG.js} +1 -1
  81. package/dist/{composition-sources-DNRZWR1j.mjs → composition-sources-BlcYzFwY.mjs} +1 -1
  82. package/dist/{constants-6OeJiZgi.js → constants-7ZMxWr8Z.js} +1 -1
  83. package/dist/{constants-BnkOdj9Q.mjs → constants-CH5UXe_G.mjs} +1 -1
  84. package/dist/{custom-action-registry-DStvrQKI.mjs → custom-action-registry-DZSCLBuT.mjs} +2 -0
  85. package/dist/{custom-action-registry-COyb49zm.js → custom-action-registry-MRyes5j0.js} +2 -0
  86. package/dist/{device-ca-Bnkw8GyU.mjs → device-ca-BU_gnd-q.mjs} +1 -1
  87. package/dist/{device-ca-CPTDs--d.js → device-ca-CUEx7sti.js} +1 -1
  88. package/dist/{dist-Wy8cTxg6.mjs → dist-8tWIDoWp.mjs} +15 -55
  89. package/dist/{dist-Bn-RNanh.js → dist-Ct-4tTeX.js} +14 -66
  90. package/dist/file-host-worker.js +1 -1
  91. package/dist/file-host-worker.mjs +1 -1
  92. package/dist/{hub-mdns-ciao-CJu0nhla.mjs → hub-mdns-ciao-Cuy7LUdz.mjs} +2 -2
  93. package/dist/{hub-mdns-ciao-CTBTlia4.js → hub-mdns-ciao-DJ-Amqd7.js} +2 -2
  94. package/dist/index.d.ts +1 -1
  95. package/dist/index.js +89 -241
  96. package/dist/index.mjs +90 -237
  97. package/dist/kernel/index.d.ts +0 -1
  98. package/dist/kernel/moleculer/runner-addon-settings.d.ts +1 -6
  99. package/dist/kernel/moleculer/runner-device-settings.d.ts +2 -2
  100. package/dist/{restore-archive-CM23Pq9B.mjs → restore-archive-BDua3jO6.mjs} +78 -78
  101. package/dist/{restore-archive-DM1OBYq4.js → restore-archive-HwOA83v3.js} +1 -1
  102. package/dist/{retired-settings-keys-D_VwZiDt.js → retired-settings-keys-CGUqX-Oz.js} +0 -6
  103. package/dist/{retired-settings-keys-Bhwe4ymb.mjs → retired-settings-keys-C_Kjp-Bj.mjs} +1 -1
  104. package/dist/{wal-maintenance-Bj_MmDkr.mjs → wal-maintenance-BvzVehem.mjs} +0 -0
  105. package/dist/{wal-maintenance-CaJjuLHq.js → wal-maintenance-DBvuVU9s.js} +0 -0
  106. package/package.json +1 -1
  107. package/dist/builtins/sqlite-storage/retired-collections.d.ts +0 -146
  108. package/dist/kernel/legacy-blob-guard.d.ts +0 -63
@@ -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-Bn-RNanh.js");
6
+ const require_dist = require("../../dist-Ct-4tTeX.js");
7
7
  const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
8
- const require_restore_archive = require("../../restore-archive-DM1OBYq4.js");
8
+ const require_restore_archive = require("../../restore-archive-HwOA83v3.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);
@@ -87,75 +87,26 @@ async function seedWeeklySchedule(store, markers) {
87
87
  //#endregion
88
88
  //#region src/builtins/backup-orchestrator/seed-marker-store.ts
89
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"
90
+ * One `seed-markers` row per seed id (D902: no `backup_seed_markers` table).
91
+ * Written once, never updated; deleting one lets that seed run once more.
95
92
  */
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
93
  var BackupSeedMarkerStore = class {
107
- store;
108
- now;
109
- declared = false;
110
94
  markersKind;
111
- constructor(store, now = Date.now, markersKind = null) {
112
- this.store = store;
113
- this.now = now;
95
+ now;
96
+ constructor(markersKind, now = Date.now) {
114
97
  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;
98
+ this.now = now;
124
99
  }
125
100
  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;
101
+ return await this.markersKind.get(seedId) !== null;
136
102
  }
137
103
  async mark(seedId) {
138
- await this.ensureDeclared();
139
104
  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
- }
105
+ const body = { seededAt: this.now() };
106
+ const data = require_restore_archive.backupOrchestratorRecordKinds["seed-markers"].schema.parse(body);
107
+ await this.markersKind.put({
108
+ id: seedId,
109
+ data
159
110
  });
160
111
  }
161
112
  };
@@ -955,165 +906,35 @@ function previewNextRuns(cron, count, after) {
955
906
  //#endregion
956
907
  //#region src/builtins/backup-orchestrator/destination-policy.ts
957
908
  var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
958
- /**
959
- * @durable class=config owner=backup-orchestrator
960
- * write="`ensureDefault` auto-creates one row the first time a `backups` storage
961
- * location is listed (enabled, retentionCount 7, no cadence of its own), an operator
962
- * edit rewrites it (`upsert` = delete + insert, carrying `last_run_at` forward so a
963
- * label change does not reset the baseline), and `recordAttempt` stamps
964
- * `last_run_at` + `last_error` on every attempted write to the destination"
965
- * retention="none — `delete(locationId)` exists but NOTHING calls it, so a policy row
966
- * outlives the `StorageLocation` it names and the table only ever grows, by one row
967
- * per backups location ever seen. Losing a row is recoverable: the next
968
- * `listDestinations` pass re-creates it from the defaults, which silently discards
969
- * the operator's own retention count. The legacy `cron` column is written NULL and
970
- * never read — it scheduled nothing after 2026-07-28 and reading it made a
971
- * destination advertise a nightly run nobody performed (D384)."
972
- */
973
- var BACKUP_DESTINATION_POLICIES = "backup_destination_policies";
974
- var BACKUP_DESTINATION_POLICIES_COLUMNS = [
975
- {
976
- name: "location_id",
977
- type: "TEXT",
978
- primaryKey: true
979
- },
980
- {
981
- name: "enabled",
982
- type: "INTEGER",
983
- notNull: true,
984
- defaultValue: 1
985
- },
986
- {
987
- name: "retention_count",
988
- type: "INTEGER",
989
- notNull: true,
990
- defaultValue: 7
991
- },
992
- {
993
- name: "label",
994
- type: "TEXT"
995
- },
996
- {
997
- name: "cron",
998
- type: "TEXT"
999
- },
1000
- {
1001
- name: "last_run_at",
1002
- type: "INTEGER"
1003
- },
1004
- {
1005
- name: "last_error",
1006
- type: "TEXT"
1007
- }
1008
- ];
1009
909
  var BackupDestinationPolicyService = class {
1010
- store;
1011
- declared = false;
1012
910
  policiesKind;
1013
- constructor(store, policiesKind = null) {
1014
- this.store = store;
911
+ constructor(policiesKind) {
1015
912
  this.policiesKind = policiesKind;
1016
913
  }
1017
- /**
1018
- * Lazy `declareCollection` — called from every read/write path.
1019
- * `declareCollection` is idempotent, so repeated calls collapse to a no-op
1020
- * after the first. This keeps the constructor synchronous and avoids a
1021
- * separate `initialize()` step that callers could forget.
1022
- */
1023
- async initialize() {
1024
- await this.ensureDeclared();
1025
- }
1026
- async ensureDeclared() {
1027
- if (this.policiesKind !== null) return;
1028
- if (this.declared) return;
1029
- await this.store.declareCollection({
1030
- collection: BACKUP_DESTINATION_POLICIES,
1031
- columns: BACKUP_DESTINATION_POLICIES_COLUMNS
1032
- });
1033
- this.declared = true;
1034
- }
1035
914
  async list() {
1036
- await this.ensureDeclared();
1037
- const kind = this.policiesKind;
1038
- if (kind !== null) {
1039
- const rows = await (0, import_read_all_rows.readAllRows)(kind);
1040
- rows.sort((a, b) => a.id.localeCompare(b.id));
1041
- const out = [];
1042
- for (const row of rows) {
1043
- const mapped = bodyToPolicy(row.id, row.data);
1044
- if (mapped) out.push(mapped);
1045
- }
1046
- return out;
1047
- }
1048
- const rows = await this.store.query({
1049
- collection: BACKUP_DESTINATION_POLICIES,
1050
- filter: { orderBy: {
1051
- field: "location_id",
1052
- direction: "asc"
1053
- } }
1054
- });
915
+ const rows = await (0, import_read_all_rows.readAllRows)(this.policiesKind);
916
+ rows.sort((a, b) => a.id.localeCompare(b.id));
1055
917
  const out = [];
1056
918
  for (const row of rows) {
1057
- const mapped = mapRowToPolicy(row.data);
919
+ const mapped = bodyToPolicy(row.id, row.data);
1058
920
  if (mapped) out.push(mapped);
1059
921
  }
1060
922
  return out;
1061
923
  }
1062
924
  async get(locationId) {
1063
- await this.ensureDeclared();
1064
- const kind = this.policiesKind;
1065
- if (kind !== null) {
1066
- const row = await kind.get(locationId);
1067
- return row === null ? null : bodyToPolicy(locationId, row.data);
1068
- }
1069
- const rows = await this.store.query({
1070
- collection: BACKUP_DESTINATION_POLICIES,
1071
- filter: {
1072
- where: { location_id: locationId },
1073
- limit: 1
1074
- }
1075
- });
1076
- return rows[0] ? mapRowToPolicy(rows[0].data) : null;
925
+ const row = await this.policiesKind.get(locationId);
926
+ return row === null ? null : bodyToPolicy(locationId, row.data);
1077
927
  }
1078
- /**
1079
- * Replace-or-insert. Implemented as delete + insert, mirroring the
1080
- * `SqliteLocationStore` contract.
1081
- */
928
+ /** Replace-or-insert: one full `put` of the row. */
1082
929
  async upsert(p) {
1083
- await this.ensureDeclared();
1084
- const kind = this.policiesKind;
1085
- if (kind !== null) {
1086
- const body = policyToBody(p);
1087
- const data = require_restore_archive.backupOrchestratorRecordKinds["destination-policies"].schema.parse(body);
1088
- await kind.put({
1089
- id: p.locationId,
1090
- data
1091
- });
1092
- return;
1093
- }
1094
- await this.store.deleteWhere({
1095
- collection: BACKUP_DESTINATION_POLICIES,
1096
- filter: { where: { location_id: p.locationId } }
1097
- });
1098
- await this.store.insert({
1099
- collection: BACKUP_DESTINATION_POLICIES,
1100
- record: {
1101
- id: p.locationId,
1102
- data: mapPolicyToRow(p)
1103
- }
930
+ const data = require_restore_archive.backupOrchestratorRecordKinds["destination-policies"].schema.parse(policyToBody(p));
931
+ await this.policiesKind.put({
932
+ id: p.locationId,
933
+ data
1104
934
  });
1105
935
  }
1106
936
  async delete(locationId) {
1107
- await this.ensureDeclared();
1108
- const kind = this.policiesKind;
1109
- if (kind !== null) {
1110
- await kind.delete(locationId);
1111
- return;
1112
- }
1113
- await this.store.deleteWhere({
1114
- collection: BACKUP_DESTINATION_POLICIES,
1115
- filter: { where: { location_id: locationId } }
1116
- });
937
+ await this.policiesKind.delete(locationId);
1117
938
  }
1118
939
  /**
1119
940
  * Auto-create a default policy for a `backups` location seen for the
@@ -1181,41 +1002,6 @@ function bodyToPolicy(locationId, body) {
1181
1002
  ...body.lastError !== void 0 ? { lastError: body.lastError } : {}
1182
1003
  };
1183
1004
  }
1184
- function mapPolicyToRow(p) {
1185
- return {
1186
- location_id: p.locationId,
1187
- enabled: p.enabled ? 1 : 0,
1188
- retention_count: p.retentionCount,
1189
- label: p.label ?? null,
1190
- cron: null,
1191
- last_run_at: p.lastAttemptAt ?? null,
1192
- last_error: p.lastError ?? null
1193
- };
1194
- }
1195
- /**
1196
- * Decode a row pulled from the structured table. Defensive against
1197
- * schema drift / partial migrations: returns `null` on missing
1198
- * `location_id` so corrupt rows skip the result list rather than
1199
- * throwing the whole orchestrator down at boot.
1200
- */
1201
- function mapRowToPolicy(row) {
1202
- const locationId = String(row["location_id"] ?? "");
1203
- if (!locationId) return null;
1204
- const labelRaw = row["label"];
1205
- const label = typeof labelRaw === "string" && labelRaw.length > 0 ? labelRaw : void 0;
1206
- const lastRunRaw = row["last_run_at"];
1207
- const lastAttemptAt = typeof lastRunRaw === "number" && lastRunRaw > 0 ? lastRunRaw : void 0;
1208
- const lastErrorRaw = row["last_error"];
1209
- const lastError = typeof lastErrorRaw === "string" && lastErrorRaw.length > 0 ? lastErrorRaw : void 0;
1210
- return {
1211
- locationId,
1212
- enabled: row["enabled"] === 1 || row["enabled"] === true,
1213
- retentionCount: Number(row["retention_count"] ?? 0),
1214
- ...label !== void 0 ? { label } : {},
1215
- ...lastAttemptAt !== void 0 ? { lastAttemptAt } : {},
1216
- ...lastError !== void 0 ? { lastError } : {}
1217
- };
1218
- }
1219
1005
  //#endregion
1220
1006
  //#region src/builtins/backup-orchestrator/download-helpers.ts
1221
1007
  /**
@@ -1908,176 +1694,35 @@ function requestSignature(request) {
1908
1694
  }
1909
1695
  //#endregion
1910
1696
  //#region src/builtins/backup-orchestrator/schedule-store.ts
1911
- /**
1912
- * @durable class=config owner=backup-orchestrator
1913
- * write="an operator creating or editing a schedule (`upsert`, implemented as
1914
- * delete + insert: cron, enabled, the fan-out `location_ids`, `retention_count`,
1915
- * optional `data_sources`), plus a `last_run_at` stamp the orchestrator writes on
1916
- * every due tick BEFORE the archive runs, so an upload outliving the tick cannot
1917
- * fire the same schedule twice, and a `last_success_at` / `last_error` pair it
1918
- * writes AFTER the run resolves"
1919
- * retention="only the operator's `delete(id)` — no sweep, no expiry, and `retention_count`
1920
- * bounds the ARCHIVES at the destination, never these rows. Losing the table stops
1921
- * every scheduled backup silently: no cron remains to fire, and the fan-out sets and
1922
- * retention counts are gone with it."
1923
- */
1924
- var BACKUP_SCHEDULES = "backup_schedules";
1925
- var BACKUP_SCHEDULES_COLUMNS = [
1926
- {
1927
- name: "id",
1928
- type: "TEXT",
1929
- primaryKey: true
1930
- },
1931
- {
1932
- name: "label",
1933
- type: "TEXT",
1934
- notNull: true,
1935
- defaultValue: ""
1936
- },
1937
- {
1938
- name: "cron",
1939
- type: "TEXT",
1940
- notNull: true,
1941
- defaultValue: ""
1942
- },
1943
- {
1944
- name: "enabled",
1945
- type: "INTEGER",
1946
- notNull: true,
1947
- defaultValue: 1
1948
- },
1949
- {
1950
- name: "location_ids",
1951
- type: "JSON",
1952
- notNull: true,
1953
- defaultValue: "[]"
1954
- },
1955
- {
1956
- name: "retention_count",
1957
- type: "INTEGER",
1958
- notNull: true,
1959
- defaultValue: 7
1960
- },
1961
- {
1962
- name: "data_sources",
1963
- type: "JSON"
1964
- },
1965
- {
1966
- name: "databases",
1967
- type: "JSON"
1968
- },
1969
- {
1970
- name: "last_run_at",
1971
- type: "INTEGER"
1972
- },
1973
- {
1974
- name: "last_success_at",
1975
- type: "INTEGER"
1976
- },
1977
- {
1978
- name: "last_error",
1979
- type: "TEXT"
1980
- }
1981
- ];
1982
1697
  var BackupScheduleService = class {
1983
- store;
1984
- declared = false;
1985
1698
  schedulesKind;
1986
- constructor(store, schedulesKind = null) {
1987
- this.store = store;
1699
+ constructor(schedulesKind) {
1988
1700
  this.schedulesKind = schedulesKind;
1989
1701
  }
1990
- async initialize() {
1991
- await this.ensureDeclared();
1992
- }
1993
- async ensureDeclared() {
1994
- if (this.schedulesKind !== null) return;
1995
- if (this.declared) return;
1996
- await this.store.declareCollection({
1997
- collection: BACKUP_SCHEDULES,
1998
- columns: BACKUP_SCHEDULES_COLUMNS
1999
- });
2000
- this.declared = true;
2001
- }
2002
1702
  async list() {
2003
- await this.ensureDeclared();
2004
- const kind = this.schedulesKind;
2005
- if (kind !== null) {
2006
- const rows = await (0, import_read_all_rows.readAllRows)(kind);
2007
- rows.sort((a, b) => a.id.localeCompare(b.id));
2008
- const out = [];
2009
- for (const row of rows) {
2010
- const mapped = bodyToSchedule(row.id, row.data);
2011
- if (mapped) out.push(mapped);
2012
- }
2013
- return out;
2014
- }
2015
- const rows = await this.store.query({
2016
- collection: BACKUP_SCHEDULES,
2017
- filter: { orderBy: {
2018
- field: "id",
2019
- direction: "asc"
2020
- } }
2021
- });
1703
+ const rows = await (0, import_read_all_rows.readAllRows)(this.schedulesKind);
1704
+ rows.sort((a, b) => a.id.localeCompare(b.id));
2022
1705
  const out = [];
2023
1706
  for (const row of rows) {
2024
- const mapped = mapRowToSchedule(row.data);
1707
+ const mapped = bodyToSchedule(row.id, row.data);
2025
1708
  if (mapped) out.push(mapped);
2026
1709
  }
2027
1710
  return out;
2028
1711
  }
2029
1712
  async get(id) {
2030
- await this.ensureDeclared();
2031
- const kind = this.schedulesKind;
2032
- if (kind !== null) {
2033
- const row = await kind.get(id);
2034
- return row === null ? null : bodyToSchedule(id, row.data);
2035
- }
2036
- const rows = await this.store.query({
2037
- collection: BACKUP_SCHEDULES,
2038
- filter: {
2039
- where: { id },
2040
- limit: 1
2041
- }
2042
- });
2043
- return rows[0] ? mapRowToSchedule(rows[0].data) : null;
1713
+ const row = await this.schedulesKind.get(id);
1714
+ return row === null ? null : bodyToSchedule(id, row.data);
2044
1715
  }
2045
- /** Replace-or-insert (delete + insert — mirrors the policy store). */
1716
+ /** Replace-or-insert: one full `put` of the row. */
2046
1717
  async upsert(s) {
2047
- await this.ensureDeclared();
2048
- const kind = this.schedulesKind;
2049
- if (kind !== null) {
2050
- const body = scheduleToBody(s);
2051
- const data = require_restore_archive.backupOrchestratorRecordKinds.schedules.schema.parse(body);
2052
- await kind.put({
2053
- id: s.id,
2054
- data
2055
- });
2056
- return;
2057
- }
2058
- await this.store.deleteWhere({
2059
- collection: BACKUP_SCHEDULES,
2060
- filter: { where: { id: s.id } }
2061
- });
2062
- await this.store.insert({
2063
- collection: BACKUP_SCHEDULES,
2064
- record: {
2065
- id: s.id,
2066
- data: mapScheduleToRow(s)
2067
- }
1718
+ const data = require_restore_archive.backupOrchestratorRecordKinds.schedules.schema.parse(scheduleToBody(s));
1719
+ await this.schedulesKind.put({
1720
+ id: s.id,
1721
+ data
2068
1722
  });
2069
1723
  }
2070
1724
  async delete(id) {
2071
- await this.ensureDeclared();
2072
- const kind = this.schedulesKind;
2073
- if (kind !== null) {
2074
- await kind.delete(id);
2075
- return;
2076
- }
2077
- await this.store.deleteWhere({
2078
- collection: BACKUP_SCHEDULES,
2079
- filter: { where: { id } }
2080
- });
1725
+ await this.schedulesKind.delete(id);
2081
1726
  }
2082
1727
  };
2083
1728
  function scheduleToBody(s) {
@@ -2110,73 +1755,6 @@ function bodyToSchedule(id, body) {
2110
1755
  ...body.lastError !== void 0 ? { lastError: body.lastError } : {}
2111
1756
  };
2112
1757
  }
2113
- function mapScheduleToRow(s) {
2114
- return {
2115
- id: s.id,
2116
- label: s.label,
2117
- cron: s.cron,
2118
- enabled: s.enabled ? 1 : 0,
2119
- location_ids: [...s.locationIds],
2120
- retention_count: s.retentionCount,
2121
- data_sources: s.dataSources ? [...s.dataSources] : null,
2122
- databases: s.databases ? [...s.databases] : null,
2123
- last_run_at: s.lastAttemptAt ?? null,
2124
- last_success_at: s.lastSuccessAt ?? null,
2125
- last_error: s.lastError ?? null
2126
- };
2127
- }
2128
- /**
2129
- * `location_ids` / `data_sources` are `JSON` columns, so the surface hands
2130
- * back real arrays. A STRING still arrives for rows an older build wrote and
2131
- * nothing has rewritten since — a schedule whose fan-out set silently read as
2132
- * empty would back up to nowhere, so both shapes are accepted.
2133
- */
2134
- function parseStringArray(raw) {
2135
- const value = typeof raw === "string" ? tryParseJson(raw) : raw;
2136
- if (!Array.isArray(value)) return [];
2137
- return value.filter((v) => typeof v === "string");
2138
- }
2139
- /** Known database ids only: an unknown name in a stored row is dropped, not carried. */
2140
- function parseDatabaseIds(raw) {
2141
- const out = [];
2142
- for (const id of parseStringArray(raw)) if (id === "settings" || id === "events" || id === "history") out.push(id);
2143
- return out;
2144
- }
2145
- function tryParseJson(raw) {
2146
- if (raw.length === 0) return null;
2147
- try {
2148
- return JSON.parse(raw);
2149
- } catch {
2150
- return null;
2151
- }
2152
- }
2153
- function mapRowToSchedule(row) {
2154
- const id = String(row["id"] ?? "");
2155
- if (!id) return null;
2156
- const dataSourcesRaw = row["data_sources"];
2157
- const dataSources = dataSourcesRaw === null || dataSourcesRaw === void 0 ? void 0 : parseStringArray(dataSourcesRaw);
2158
- const databasesRaw = row["databases"];
2159
- const databases = databasesRaw === null || databasesRaw === void 0 ? void 0 : parseDatabaseIds(databasesRaw);
2160
- const lastRunRaw = row["last_run_at"];
2161
- const lastAttemptAt = typeof lastRunRaw === "number" && lastRunRaw > 0 ? lastRunRaw : void 0;
2162
- const lastSuccessRaw = row["last_success_at"];
2163
- const lastSuccessAt = typeof lastSuccessRaw === "number" && lastSuccessRaw > 0 ? lastSuccessRaw : void 0;
2164
- const lastErrorRaw = row["last_error"];
2165
- const lastError = typeof lastErrorRaw === "string" && lastErrorRaw.length > 0 ? lastErrorRaw : void 0;
2166
- return {
2167
- id,
2168
- label: typeof row["label"] === "string" ? String(row["label"]) : "",
2169
- cron: typeof row["cron"] === "string" ? String(row["cron"]) : "",
2170
- enabled: row["enabled"] === 1 || row["enabled"] === true,
2171
- locationIds: parseStringArray(row["location_ids"]),
2172
- retentionCount: Number(row["retention_count"] ?? 7),
2173
- ...dataSources !== void 0 ? { dataSources } : {},
2174
- ...databases !== void 0 && databases.length > 0 ? { databases } : {},
2175
- ...lastAttemptAt !== void 0 ? { lastAttemptAt } : {},
2176
- ...lastSuccessAt !== void 0 ? { lastSuccessAt } : {},
2177
- ...lastError !== void 0 ? { lastError } : {}
2178
- };
2179
- }
2180
1758
  //#endregion
2181
1759
  //#region src/builtins/backup-orchestrator/staging-paths.ts
2182
1760
  /** Basename of the staging dir under the node data root. */
@@ -2308,8 +1886,8 @@ function selectBackupTargets(input) {
2308
1886
  * Responsibilities:
2309
1887
  * - Schedule (cron-like timer at top of hour, daily/weekly cadence)
2310
1888
  * - Per-destination policy (enable/disable, retention count, label)
2311
- * persisted in `backup_destination_policies` (this builtin owns
2312
- * the table).
1889
+ * persisted in the `destination-policies` records kind (this builtin
1890
+ * owns the kind).
2313
1891
  * - Archive build (one tar.gz with embedded manifest, fanned out to
2314
1892
  * every selected `backups`-typed `StorageLocation` via the
2315
1893
  * consumer-facing `storage` cap's chunked upload protocol).
@@ -2320,7 +1898,7 @@ function selectBackupTargets(input) {
2320
1898
  * Storage routing: destinations are
2321
1899
  * `api.storage.listLocations({ type: 'backups' })` — every operator-
2322
1900
  * visible `backups` location IS a destination. The orchestrator joins
2323
- * that list with the `backup_destination_policies` table to surface
1901
+ * that list with the `destination-policies` records to surface
2324
1902
  * `enabled` / `retentionCount` / `label`. The actual archive bytes
2325
1903
  * travel through `api.storage.beginUpload` / `writeChunk` /
2326
1904
  * `finalizeUpload`, with the staging archive built into
@@ -2416,19 +1994,11 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
2416
1994
  this.systemBackup = new require_restore_archive.SystemBackupService(this.dataDir, this.ctx.logger);
2417
1995
  this.runQueue = new BackupRunQueue((request, signal, progress) => this.runBackupBuild(request, signal, progress));
2418
1996
  await this.cleanStagingArea();
2419
- this.policies = this.resolvePolicyService();
2420
- if (this.policies) try {
2421
- await this.policies.initialize();
2422
- } catch (err) {
2423
- this.ctx.logger.error("backup-orchestrator: policy table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
2424
- this.policies = null;
2425
- }
2426
- this.schedules = this.resolveScheduleService();
2427
- if (this.schedules) try {
2428
- await this.schedules.initialize();
2429
- } catch (err) {
2430
- this.ctx.logger.error("backup-orchestrator: schedule table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
2431
- this.schedules = null;
1997
+ const backupRecords = this.backupRecords;
1998
+ if (backupRecords === null) this.ctx.logger.warn("backup-orchestrator: no ctx.records — schedules and destination policies will not persist");
1999
+ else {
2000
+ this.policies = new BackupDestinationPolicyService(backupRecords.destinationPolicies);
2001
+ this.schedules = new BackupScheduleService(backupRecords.schedules);
2432
2002
  }
2433
2003
  await this.seedWeekly();
2434
2004
  const settingsStore = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
@@ -2542,7 +2112,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
2542
2112
  * lazily seeding a default for any `locationId` we haven't seen
2543
2113
  * before. Idempotent — `ensureDefault` no-ops on already-persisted
2544
2114
  * rows. Falls back to the in-memory default policy when the policy
2545
- * service isn't wired (no settings-store backend available).
2115
+ * service isn't wired (no `ctx.records`).
2546
2116
  */
2547
2117
  async loadPoliciesIndexed(locationIds) {
2548
2118
  const out = /* @__PURE__ */ new Map();
@@ -3048,7 +2618,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
3048
2618
  */
3049
2619
  async upsertDestinationPolicy(input) {
3050
2620
  if (!this.policies) {
3051
- this.ctx.logger.warn("backup upsertDestinationPolicy: no settings-store backend — change will not persist", { meta: { locationId: input.locationId } });
2621
+ this.ctx.logger.warn("backup upsertDestinationPolicy: no ctx.records — change will not persist", { meta: { locationId: input.locationId } });
3052
2622
  return;
3053
2623
  }
3054
2624
  const existing = await this.policies.get(input.locationId).catch(() => null);
@@ -3431,11 +3001,10 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
3431
3001
  * anything the operator has: see `planWeeklySeed`.
3432
3002
  */
3433
3003
  async seedWeekly() {
3434
- if (!this.schedules) return;
3004
+ const markers = this.backupRecords?.seedMarkers;
3005
+ if (!this.schedules || markers === void 0) return;
3435
3006
  try {
3436
- const store = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
3437
- if (!store) return;
3438
- const seed = await seedWeeklySchedule(this.schedules, new BackupSeedMarkerStore(store, Date.now, this.backupRecords?.seedMarkers ?? null));
3007
+ const seed = await seedWeeklySchedule(this.schedules, new BackupSeedMarkerStore(markers));
3439
3008
  if (seed === null) return;
3440
3009
  this.ctx.logger.info("backup: seeded the weekly events & history schedule", { meta: {
3441
3010
  scheduleId: seed.id,
@@ -3541,7 +3110,7 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
3541
3110
  });
3542
3111
  }
3543
3112
  async upsertSchedule(input) {
3544
- if (!this.schedules) throw new Error("backup upsertSchedule: no settings-store backend — schedule cannot be persisted");
3113
+ if (!this.schedules) throw new Error("backup upsertSchedule: no ctx.records — schedule cannot be persisted");
3545
3114
  const cron = input.cron.trim();
3546
3115
  if (cron.length > 0 && !isValidCron(cron)) throw new Error(`Invalid cron expression: "${cron}"`);
3547
3116
  const id = input.id && input.id.length > 0 ? input.id : (0, node_crypto.randomUUID)();
@@ -3584,26 +3153,6 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
3584
3153
  if (!this.schedules) return;
3585
3154
  await this.schedules.delete(input.id);
3586
3155
  }
3587
- resolveScheduleService() {
3588
- const reg = this.ctx.kernel.capabilityRegistry;
3589
- if (!reg) return null;
3590
- const store = reg.getSingleton("settings-store");
3591
- if (!store) {
3592
- this.ctx.logger.warn("backup-orchestrator: no settings-store provider — backup schedules will not persist");
3593
- return null;
3594
- }
3595
- return new BackupScheduleService(store, this.backupRecords?.schedules ?? null);
3596
- }
3597
- resolvePolicyService() {
3598
- const reg = this.ctx.kernel.capabilityRegistry;
3599
- if (!reg) return null;
3600
- const store = reg.getSingleton("settings-store");
3601
- if (!store) {
3602
- this.ctx.logger.warn("backup-orchestrator: no settings-store provider — destination policies will not persist");
3603
- return null;
3604
- }
3605
- return new BackupDestinationPolicyService(store, this.backupRecords?.destinationPolicies ?? null);
3606
- }
3607
3156
  /**
3608
3157
  * Narrow `ctx.api.storage` to the subset the manifest helpers need.
3609
3158
  * Lets the helpers be unit-tested with a Map-backed fake without