camstack 1.2.198 → 1.2.200

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.
@@ -24024,9 +24024,9 @@ var require_zod = __commonJS({
24024
24024
  }
24025
24025
  });
24026
24026
 
24027
- // ../system/dist/dist-Bn-RNanh.js
24028
- var require_dist_Bn_RNanh = __commonJS({
24029
- "../system/dist/dist-Bn-RNanh.js"(exports) {
24027
+ // ../system/dist/dist-D9aw_d0G.js
24028
+ var require_dist_D9aw_d0G = __commonJS({
24029
+ "../system/dist/dist-D9aw_d0G.js"(exports) {
24030
24030
  "use strict";
24031
24031
  var zod = require_zod();
24032
24032
  __require("crypto");
@@ -24239,21 +24239,21 @@ var require_dist_Bn_RNanh = __commonJS({
24239
24239
  for (const section of sectionsOf(schema)) for (const field of fieldsOf(section)) walkField(field, keys);
24240
24240
  return keys;
24241
24241
  }
24242
- function isRecord$6(value) {
24242
+ function isRecord$7(value) {
24243
24243
  return typeof value === "object" && value !== null && !Array.isArray(value);
24244
24244
  }
24245
24245
  function sectionsOf(schema) {
24246
- if (!isRecord$6(schema)) return [];
24246
+ if (!isRecord$7(schema)) return [];
24247
24247
  const sections = schema["sections"];
24248
24248
  return Array.isArray(sections) ? sections : [];
24249
24249
  }
24250
24250
  function fieldsOf(node) {
24251
- if (!isRecord$6(node)) return [];
24251
+ if (!isRecord$7(node)) return [];
24252
24252
  const fields = node["fields"];
24253
24253
  return Array.isArray(fields) ? fields : [];
24254
24254
  }
24255
24255
  function walkField(field, out) {
24256
- if (!isRecord$6(field)) return;
24256
+ if (!isRecord$7(field)) return;
24257
24257
  const type = field["type"];
24258
24258
  const key = field["key"];
24259
24259
  if ((type === "password" || field["secret"] === true) && typeof key === "string" && key.length > 0) out.add(key);
@@ -24269,7 +24269,7 @@ var require_dist_Bn_RNanh = __commonJS({
24269
24269
  }
24270
24270
  var SECRET_CLEAR = { $secretClear: true };
24271
24271
  var LEGACY_DEVICE_REDACTION = "***";
24272
- function isRecord$5(value) {
24272
+ function isRecord$6(value) {
24273
24273
  return typeof value === "object" && value !== null && !Array.isArray(value);
24274
24274
  }
24275
24275
  function makeSecretMarker(ref) {
@@ -24279,15 +24279,15 @@ var require_dist_Bn_RNanh = __commonJS({
24279
24279
  };
24280
24280
  }
24281
24281
  function isSecretMarker(value) {
24282
- if (!isRecord$5(value)) return false;
24282
+ if (!isRecord$6(value)) return false;
24283
24283
  const ref = value["$secret"];
24284
24284
  return typeof ref === "string" && ref.length > 0;
24285
24285
  }
24286
24286
  function isSecretMarkerLike(value) {
24287
- return isRecord$5(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
24287
+ return isRecord$6(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
24288
24288
  }
24289
24289
  function isSecretClear(value) {
24290
- return isRecord$5(value) && value["$secretClear"] === true;
24290
+ return isRecord$6(value) && value["$secretClear"] === true;
24291
24291
  }
24292
24292
  function toSecretFieldView(stored) {
24293
24293
  if (isSecretMarker(stored)) return {
@@ -24814,7 +24814,7 @@ var require_dist_Bn_RNanh = __commonJS({
24814
24814
  }
24815
24815
  };
24816
24816
  var KEEP = { kind: "keep" };
24817
- function isRecord$4(value) {
24817
+ function isRecord$5(value) {
24818
24818
  return typeof value === "object" && value !== null && !Array.isArray(value);
24819
24819
  }
24820
24820
  function defaultMintId() {
@@ -24826,7 +24826,7 @@ var require_dist_Bn_RNanh = __commonJS({
24826
24826
  return out;
24827
24827
  }
24828
24828
  if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
24829
- else if (isRecord$4(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
24829
+ else if (isRecord$5(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
24830
24830
  return out;
24831
24831
  }
24832
24832
  async function storedValueEquals(secrets, marker, candidate) {
@@ -24880,7 +24880,7 @@ var require_dist_Bn_RNanh = __commonJS({
24880
24880
  return null;
24881
24881
  }
24882
24882
  async function writeArray(ctx, node, incoming, stored, fieldPath) {
24883
- const storedRows = Array.isArray(stored) ? stored.filter(isRecord$4) : [];
24883
+ const storedRows = Array.isArray(stored) ? stored.filter(isRecord$5) : [];
24884
24884
  if (!Array.isArray(incoming)) {
24885
24885
  ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
24886
24886
  return {
@@ -24896,7 +24896,7 @@ var require_dist_Bn_RNanh = __commonJS({
24896
24896
  const kept = /* @__PURE__ */ new Set();
24897
24897
  const rows = [];
24898
24898
  for (const row of incoming) {
24899
- if (!isRecord$4(row)) {
24899
+ if (!isRecord$5(row)) {
24900
24900
  rows.push(row);
24901
24901
  continue;
24902
24902
  }
@@ -24923,7 +24923,7 @@ var require_dist_Bn_RNanh = __commonJS({
24923
24923
  case "array":
24924
24924
  return writeArray(ctx, node, incoming, stored, fieldPath);
24925
24925
  case "object": {
24926
- if (!isRecord$4(incoming)) {
24926
+ if (!isRecord$5(incoming)) {
24927
24927
  if (incoming === void 0) return KEEP;
24928
24928
  ctx.deletes.push(...collectSecretMarkerRefs(stored));
24929
24929
  return {
@@ -24931,7 +24931,7 @@ var require_dist_Bn_RNanh = __commonJS({
24931
24931
  value: incoming
24932
24932
  };
24933
24933
  }
24934
- const storedObj = isRecord$4(stored) ? stored : {};
24934
+ const storedObj = isRecord$5(stored) ? stored : {};
24935
24935
  return {
24936
24936
  kind: "value",
24937
24937
  value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
@@ -25047,7 +25047,7 @@ var require_dist_Bn_RNanh = __commonJS({
25047
25047
  value: items
25048
25048
  };
25049
25049
  }
25050
- if (isRecord$4(v)) {
25050
+ if (isRecord$5(v)) {
25051
25051
  const out = {};
25052
25052
  for (const [k, child] of Object.entries(v)) {
25053
25053
  const s = substitute(child);
@@ -25078,7 +25078,7 @@ var require_dist_Bn_RNanh = __commonJS({
25078
25078
  this.name = "SecretOverwriteRefusedError";
25079
25079
  }
25080
25080
  };
25081
- function isRecord$3(value) {
25081
+ function isRecord$4(value) {
25082
25082
  return typeof value === "object" && value !== null && !Array.isArray(value);
25083
25083
  }
25084
25084
  function resolvedValue(pass, marker) {
@@ -25107,7 +25107,7 @@ var require_dist_Bn_RNanh = __commonJS({
25107
25107
  return incoming.map((item, index) => {
25108
25108
  const twin = stored[index];
25109
25109
  if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
25110
- if (isRecord$3(item) && isRecord$3(twin)) return inArrayRow(pass, item, twin);
25110
+ if (isRecord$4(item) && isRecord$4(twin)) return inArrayRow(pass, item, twin);
25111
25111
  if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
25112
25112
  return item;
25113
25113
  });
@@ -25118,7 +25118,7 @@ var require_dist_Bn_RNanh = __commonJS({
25118
25118
  const twin = stored[key];
25119
25119
  if (isSecretMarker(twin)) {
25120
25120
  if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
25121
- } else if (isRecord$3(value) && isRecord$3(twin)) out[key] = inArrayRow(pass, value, twin);
25121
+ } else if (isRecord$4(value) && isRecord$4(twin)) out[key] = inArrayRow(pass, value, twin);
25122
25122
  else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
25123
25123
  }
25124
25124
  return out;
@@ -25126,7 +25126,7 @@ var require_dist_Bn_RNanh = __commonJS({
25126
25126
  async function walk(pass, incoming, stored) {
25127
25127
  if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
25128
25128
  if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
25129
- if (!isRecord$3(incoming) || !isRecord$3(stored)) return incoming;
25129
+ if (!isRecord$4(incoming) || !isRecord$4(stored)) return incoming;
25130
25130
  const out = { ...incoming };
25131
25131
  for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
25132
25132
  return out;
@@ -25155,7 +25155,7 @@ var require_dist_Bn_RNanh = __commonJS({
25155
25155
  function isJsonEqual(a, b) {
25156
25156
  if (Object.is(a, b)) return true;
25157
25157
  if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
25158
- if (isRecord$3(a) && isRecord$3(b)) {
25158
+ if (isRecord$4(a) && isRecord$4(b)) {
25159
25159
  const keys = Object.keys(a);
25160
25160
  if (keys.length !== Object.keys(b).length) return false;
25161
25161
  return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
@@ -25177,7 +25177,7 @@ var require_dist_Bn_RNanh = __commonJS({
25177
25177
  }
25178
25178
  function nodeFromStored(value, owner) {
25179
25179
  if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
25180
- if (!isRecord$3(value)) return null;
25180
+ if (!isRecord$4(value)) return null;
25181
25181
  const children = /* @__PURE__ */ new Map();
25182
25182
  for (const [key, child] of Object.entries(value)) {
25183
25183
  const node = nodeFromStored(child, owner);
@@ -26548,17 +26548,17 @@ var require_dist_Bn_RNanh = __commonJS({
26548
26548
  }
26549
26549
  return prefixes;
26550
26550
  }
26551
- function isRecord$2(value) {
26551
+ function isRecord$3(value) {
26552
26552
  return typeof value === "object" && value !== null && !Array.isArray(value);
26553
26553
  }
26554
26554
  function elementId(element, idKey, declared, prefix) {
26555
- const id = isRecord$2(element) ? element[idKey] : void 0;
26555
+ const id = isRecord$3(element) ? element[idKey] : void 0;
26556
26556
  if (typeof id !== "string" || id.length === 0) throw new InvalidRecordError(`"${declared}": every element of "${prefix}" needs a non-empty string "${idKey}" to carry a secret`);
26557
26557
  return id;
26558
26558
  }
26559
26559
  var REMOVE_LEAF = /* @__PURE__ */ Symbol("remove-leaf");
26560
26560
  function mapAt(node, segments, index, walkedKeys, concretePrefix, declared, arrayKeys, visit) {
26561
- if (!isRecord$2(node)) return node;
26561
+ if (!isRecord$3(node)) return node;
26562
26562
  const segment = segments[index];
26563
26563
  if (segment === void 0) return node;
26564
26564
  if (!Object.prototype.hasOwnProperty.call(node, segment.key)) return node;
@@ -37046,19 +37046,6 @@ var require_dist_Bn_RNanh = __commonJS({
37046
37046
  /** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
37047
37047
  declaration: RecordKindDeclarationSchema
37048
37048
  });
37049
- var STORAGE_ADMIN_MOVED_COLLECTIONS = [
37050
- "stream-broker:probe-snapshots",
37051
- "stream-broker:profile-map",
37052
- "stream-broker:rtsp-tokens",
37053
- "notification-center:device-mutes",
37054
- "recorder:recording-configs",
37055
- "pipeline-orchestrator:device-features"
37056
- ];
37057
- var STORAGE_ADMIN_SCOPED_BASES = [
37058
- "addon-settings",
37059
- "addon-devices",
37060
- "sections"
37061
- ];
37062
37049
  var storageAdminCapability = {
37063
37050
  name: "storage-admin",
37064
37051
  scope: "system",
@@ -37070,26 +37057,6 @@ var require_dist_Bn_RNanh = __commonJS({
37070
37057
  * optionally only those owned by `ownerPrefix`. Reads only.
37071
37058
  */
37072
37059
  listTables: method(zod.z.object({ ownerPrefix: zod.z.string().min(1).optional() }), zod.z.object({ tables: zod.z.array(StorageTableSchema) }), { auth: "admin" }),
37073
- /**
37074
- * Drop one table. REFUSES when an addon declared it since the engine
37075
- * started (a running addon still owns it), when it is an engine or
37076
- * canonical table, when it does not exist, or when its row count is not
37077
- * `expectRows` - the caller states what it believes it is deleting. The
37078
- * engine also refuses anything but `<owner>:(addon-settings|addon-devices|
37079
- * sections)`, the retired collections by name, and tables of owners that
37080
- * are not installed (and refuses when it cannot read the installed list).
37081
- * Removed with the D870 migration script once the last hub ran it.
37082
- */
37083
- dropCollection: method(zod.z.object({
37084
- collection: zod.z.string().min(1),
37085
- expectRows: zod.z.number().int().nonnegative()
37086
- }), zod.z.object({
37087
- dropped: zod.z.literal(true),
37088
- rows: zod.z.number().int().nonnegative()
37089
- }), {
37090
- kind: "mutation",
37091
- auth: "admin"
37092
- }),
37093
37060
  /** Every record kind of both files with rows, a size estimate, class and retention (D881). */
37094
37061
  listKinds: method(zod.z.object({
37095
37062
  owner: zod.z.string().min(1).optional(),
@@ -63642,6 +63609,15 @@ var require_dist_Bn_RNanh = __commonJS({
63642
63609
  * Replaces `zoneCrop`.
63643
63610
  */
63644
63611
  showTriggerZone: zod.z.boolean().optional(),
63612
+ /**
63613
+ * Draw the SUBJECT'S PATH on the picture — a line in the subject's colour
63614
+ * through the track's positions up to the frame shown, the same path the
63615
+ * debug views draw (`buildSubjectPath`, D903). Every picture mode a subject
63616
+ * is drawn on: a `crop` maps the path into the crop and clips it. Valid only
63617
+ * on a rule whose subject is a tracked object (refused on a sound rule);
63618
+ * dropped on `image: 'none'`. Absent = off.
63619
+ */
63620
+ showSubjectPath: zod.z.boolean().optional(),
63645
63621
  /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
63646
63622
  attach: zod.z.enum([
63647
63623
  "best",
@@ -94558,12 +94534,6 @@ var require_dist_Bn_RNanh = __commonJS({
94558
94534
  addonId: null,
94559
94535
  access: "create"
94560
94536
  },
94561
- "storageAdmin.dropCollection": {
94562
- capName: "storage-admin",
94563
- capScope: "system",
94564
- addonId: null,
94565
- access: "delete"
94566
- },
94567
94537
  "storageAdmin.listKinds": {
94568
94538
  capName: "storage-admin",
94569
94539
  capScope: "system",
@@ -101340,18 +101310,6 @@ var require_dist_Bn_RNanh = __commonJS({
101340
101310
  return STORAGE_ACCESS_FALLBACK;
101341
101311
  }
101342
101312
  });
101343
- Object.defineProperty(exports, "STORAGE_ADMIN_MOVED_COLLECTIONS", {
101344
- enumerable: true,
101345
- get: function() {
101346
- return STORAGE_ADMIN_MOVED_COLLECTIONS;
101347
- }
101348
- });
101349
- Object.defineProperty(exports, "STORAGE_ADMIN_SCOPED_BASES", {
101350
- enumerable: true,
101351
- get: function() {
101352
- return STORAGE_ADMIN_SCOPED_BASES;
101353
- }
101354
- });
101355
101313
  Object.defineProperty(exports, "STREAM_PROFILE_META", {
101356
101314
  enumerable: true,
101357
101315
  get: function() {
@@ -114066,11 +114024,11 @@ ${values.join("\n")}` : `${blockName} :`;
114066
114024
  }
114067
114025
  });
114068
114026
 
114069
- // ../system/dist/device-ca-CPTDs--d.js
114070
- var require_device_ca_CPTDs_d = __commonJS({
114071
- "../system/dist/device-ca-CPTDs--d.js"(exports) {
114027
+ // ../system/dist/device-ca-B3xUzps7.js
114028
+ var require_device_ca_B3xUzps7 = __commonJS({
114029
+ "../system/dist/device-ca-B3xUzps7.js"(exports) {
114072
114030
  "use strict";
114073
- var require_dist10 = require_dist_Bn_RNanh();
114031
+ var require_dist10 = require_dist_D9aw_d0G();
114074
114032
  var require_x509_es = require_x509_es_C4cOo48M();
114075
114033
  var node_crypto = __require("crypto");
114076
114034
  var SYSTEM_SECRET_OWNER = "system";
@@ -114494,7 +114452,7 @@ var require_alerts_addon = __commonJS({
114494
114452
  [Symbol.toStringTag]: { value: "Module" }
114495
114453
  });
114496
114454
  require_chunk_Cek0wNdY();
114497
- var require_dist10 = require_dist_Bn_RNanh();
114455
+ var require_dist10 = require_dist_D9aw_d0G();
114498
114456
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
114499
114457
  function nextEpisodeId(input) {
114500
114458
  const { previous } = input;
@@ -115899,7 +115857,7 @@ var require_calendars_addon = __commonJS({
115899
115857
  [Symbol.toStringTag]: { value: "Module" }
115900
115858
  });
115901
115859
  require_chunk_Cek0wNdY();
115902
- var require_dist10 = require_dist_Bn_RNanh();
115860
+ var require_dist10 = require_dist_D9aw_d0G();
115903
115861
  var require_settle_sources = require_settle_sources_Bhsy57y();
115904
115862
  var zod = require_zod();
115905
115863
  var CALENDAR_COLOR_PALETTE = [
@@ -116115,11 +116073,11 @@ var require_calendars = __commonJS({
116115
116073
  }
116116
116074
  });
116117
116075
 
116118
- // ../system/dist/composition-sources-b0e_2I-D.js
116119
- var require_composition_sources_b0e_2I_D = __commonJS({
116120
- "../system/dist/composition-sources-b0e_2I-D.js"(exports) {
116076
+ // ../system/dist/composition-sources-oXvmbMHX.js
116077
+ var require_composition_sources_oXvmbMHX = __commonJS({
116078
+ "../system/dist/composition-sources-oXvmbMHX.js"(exports) {
116121
116079
  "use strict";
116122
- var require_dist10 = require_dist_Bn_RNanh();
116080
+ var require_dist10 = require_dist_D9aw_d0G();
116123
116081
  function normalizedNativeOwner(owner) {
116124
116082
  const trimmed = owner?.trim();
116125
116083
  return trimmed ? trimmed : null;
@@ -116234,8 +116192,8 @@ var require_composer_addon = __commonJS({
116234
116192
  [Symbol.toStringTag]: { value: "Module" }
116235
116193
  });
116236
116194
  require_chunk_Cek0wNdY();
116237
- var require_dist10 = require_dist_Bn_RNanh();
116238
- var require_composition_sources = require_composition_sources_b0e_2I_D();
116195
+ var require_dist10 = require_dist_D9aw_d0G();
116196
+ var require_composition_sources = require_composition_sources_oXvmbMHX();
116239
116197
  var zod = require_zod();
116240
116198
  function isRecord$2(value) {
116241
116199
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -120045,7 +120003,7 @@ var require_console_logging = __commonJS({
120045
120003
  [Symbol.toStringTag]: { value: "Module" }
120046
120004
  });
120047
120005
  require_chunk_Cek0wNdY();
120048
- var require_dist10 = require_dist_Bn_RNanh();
120006
+ var require_dist10 = require_dist_D9aw_d0G();
120049
120007
  var require_formatter = require_formatter_DqAKDlvN();
120050
120008
  var LEVEL_RANK = {
120051
120009
  debug: 0,
@@ -124709,9 +124667,9 @@ var require_core_blocks_addon = __commonJS({
124709
124667
  "use strict";
124710
124668
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
124711
124669
  var require_chunk = require_chunk_Cek0wNdY();
124712
- var require_dist10 = require_dist_Bn_RNanh();
124670
+ var require_dist10 = require_dist_D9aw_d0G();
124713
124671
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
124714
- var require_composition_sources = require_composition_sources_b0e_2I_D();
124672
+ var require_composition_sources = require_composition_sources_oXvmbMHX();
124715
124673
  var require_prefix_range = require_prefix_range_D_KueXbQ();
124716
124674
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
124717
124675
  var zod = require_zod();
@@ -127114,9 +127072,9 @@ var require_event_category_eSqkye_K = __commonJS({
127114
127072
  }
127115
127073
  });
127116
127074
 
127117
- // ../types/dist/sleep-gRQc2IoX.js
127118
- var require_sleep_gRQc2IoX = __commonJS({
127119
- "../types/dist/sleep-gRQc2IoX.js"(exports) {
127075
+ // ../types/dist/sleep-Re8daN0Y.js
127076
+ var require_sleep_Re8daN0Y = __commonJS({
127077
+ "../types/dist/sleep-Re8daN0Y.js"(exports) {
127120
127078
  "use strict";
127121
127079
  var require_event_category = require_event_category_eSqkye_K();
127122
127080
  var zod = require_zod();
@@ -127189,7 +127147,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127189
127147
  return next;
127190
127148
  }
127191
127149
  function collectOmitted(field, out) {
127192
- if (!isRecord$6(field)) return;
127150
+ if (!isRecord$7(field)) return;
127193
127151
  const type = field["type"];
127194
127152
  const key = field["key"];
127195
127153
  if (field["omitFromSettings"] === true && typeof key === "string" && key.length > 0) out.add(key);
@@ -127209,7 +127167,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127209
127167
  return keys;
127210
127168
  }
127211
127169
  function walkKeychainField(field, out) {
127212
- if (!isRecord$6(field)) return;
127170
+ if (!isRecord$7(field)) return;
127213
127171
  const type = field["type"];
127214
127172
  const key = field["key"];
127215
127173
  const isSecret = type === "password" || field["secret"] === true;
@@ -127229,21 +127187,21 @@ var require_sleep_gRQc2IoX = __commonJS({
127229
127187
  for (const section of sectionsOf(schema)) if (fieldsOf(section).length > 0) return true;
127230
127188
  return false;
127231
127189
  }
127232
- function isRecord$6(value) {
127190
+ function isRecord$7(value) {
127233
127191
  return typeof value === "object" && value !== null && !Array.isArray(value);
127234
127192
  }
127235
127193
  function sectionsOf(schema) {
127236
- if (!isRecord$6(schema)) return [];
127194
+ if (!isRecord$7(schema)) return [];
127237
127195
  const sections = schema["sections"];
127238
127196
  return Array.isArray(sections) ? sections : [];
127239
127197
  }
127240
127198
  function fieldsOf(node) {
127241
- if (!isRecord$6(node)) return [];
127199
+ if (!isRecord$7(node)) return [];
127242
127200
  const fields = node["fields"];
127243
127201
  return Array.isArray(fields) ? fields : [];
127244
127202
  }
127245
127203
  function walkField(field, out) {
127246
- if (!isRecord$6(field)) return;
127204
+ if (!isRecord$7(field)) return;
127247
127205
  const type = field["type"];
127248
127206
  const key = field["key"];
127249
127207
  if ((type === "password" || field["secret"] === true) && typeof key === "string" && key.length > 0) out.add(key);
@@ -127259,7 +127217,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127259
127217
  }
127260
127218
  var SECRET_CLEAR = { $secretClear: true };
127261
127219
  var LEGACY_DEVICE_REDACTION = "***";
127262
- function isRecord$5(value) {
127220
+ function isRecord$6(value) {
127263
127221
  return typeof value === "object" && value !== null && !Array.isArray(value);
127264
127222
  }
127265
127223
  function makeSecretMarker(ref) {
@@ -127269,18 +127227,18 @@ var require_sleep_gRQc2IoX = __commonJS({
127269
127227
  };
127270
127228
  }
127271
127229
  function isSecretMarker(value) {
127272
- if (!isRecord$5(value)) return false;
127230
+ if (!isRecord$6(value)) return false;
127273
127231
  const ref = value["$secret"];
127274
127232
  return typeof ref === "string" && ref.length > 0;
127275
127233
  }
127276
127234
  function isSecretMarkerLike(value) {
127277
- return isRecord$5(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
127235
+ return isRecord$6(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
127278
127236
  }
127279
127237
  function isSecretClear(value) {
127280
- return isRecord$5(value) && value["$secretClear"] === true;
127238
+ return isRecord$6(value) && value["$secretClear"] === true;
127281
127239
  }
127282
127240
  function isSecretFieldView(value) {
127283
- return isRecord$5(value) && value["set"] === true && isSecretMarkerLike(value);
127241
+ return isRecord$6(value) && value["set"] === true && isSecretMarkerLike(value);
127284
127242
  }
127285
127243
  function toSecretFieldView(stored) {
127286
127244
  if (isSecretMarker(stored)) return {
@@ -127878,7 +127836,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127878
127836
  }
127879
127837
  };
127880
127838
  var KEEP = { kind: "keep" };
127881
- function isRecord$4(value) {
127839
+ function isRecord$5(value) {
127882
127840
  return typeof value === "object" && value !== null && !Array.isArray(value);
127883
127841
  }
127884
127842
  function defaultMintId() {
@@ -127890,7 +127848,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127890
127848
  return out;
127891
127849
  }
127892
127850
  if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
127893
- else if (isRecord$4(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
127851
+ else if (isRecord$5(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
127894
127852
  return out;
127895
127853
  }
127896
127854
  async function storedValueEquals(secrets, marker, candidate) {
@@ -127944,7 +127902,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127944
127902
  return null;
127945
127903
  }
127946
127904
  async function writeArray(ctx, node, incoming, stored, fieldPath) {
127947
- const storedRows = Array.isArray(stored) ? stored.filter(isRecord$4) : [];
127905
+ const storedRows = Array.isArray(stored) ? stored.filter(isRecord$5) : [];
127948
127906
  if (!Array.isArray(incoming)) {
127949
127907
  ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
127950
127908
  return {
@@ -127960,7 +127918,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127960
127918
  const kept = /* @__PURE__ */ new Set();
127961
127919
  const rows = [];
127962
127920
  for (const row of incoming) {
127963
- if (!isRecord$4(row)) {
127921
+ if (!isRecord$5(row)) {
127964
127922
  rows.push(row);
127965
127923
  continue;
127966
127924
  }
@@ -127987,7 +127945,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127987
127945
  case "array":
127988
127946
  return writeArray(ctx, node, incoming, stored, fieldPath);
127989
127947
  case "object": {
127990
- if (!isRecord$4(incoming)) {
127948
+ if (!isRecord$5(incoming)) {
127991
127949
  if (incoming === void 0) return KEEP;
127992
127950
  ctx.deletes.push(...collectSecretMarkerRefs(stored));
127993
127951
  return {
@@ -127995,7 +127953,7 @@ var require_sleep_gRQc2IoX = __commonJS({
127995
127953
  value: incoming
127996
127954
  };
127997
127955
  }
127998
- const storedObj = isRecord$4(stored) ? stored : {};
127956
+ const storedObj = isRecord$5(stored) ? stored : {};
127999
127957
  return {
128000
127958
  kind: "value",
128001
127959
  value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
@@ -128111,7 +128069,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128111
128069
  value: items
128112
128070
  };
128113
128071
  }
128114
- if (isRecord$4(v)) {
128072
+ if (isRecord$5(v)) {
128115
128073
  const out = {};
128116
128074
  for (const [k, child] of Object.entries(v)) {
128117
128075
  const s = substitute(child);
@@ -128142,7 +128100,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128142
128100
  this.name = "SecretOverwriteRefusedError";
128143
128101
  }
128144
128102
  };
128145
- function isRecord$3(value) {
128103
+ function isRecord$4(value) {
128146
128104
  return typeof value === "object" && value !== null && !Array.isArray(value);
128147
128105
  }
128148
128106
  function resolvedValue(pass, marker) {
@@ -128171,7 +128129,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128171
128129
  return incoming.map((item, index) => {
128172
128130
  const twin = stored[index];
128173
128131
  if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
128174
- if (isRecord$3(item) && isRecord$3(twin)) return inArrayRow(pass, item, twin);
128132
+ if (isRecord$4(item) && isRecord$4(twin)) return inArrayRow(pass, item, twin);
128175
128133
  if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
128176
128134
  return item;
128177
128135
  });
@@ -128182,7 +128140,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128182
128140
  const twin = stored[key];
128183
128141
  if (isSecretMarker(twin)) {
128184
128142
  if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
128185
- } else if (isRecord$3(value) && isRecord$3(twin)) out[key] = inArrayRow(pass, value, twin);
128143
+ } else if (isRecord$4(value) && isRecord$4(twin)) out[key] = inArrayRow(pass, value, twin);
128186
128144
  else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
128187
128145
  }
128188
128146
  return out;
@@ -128190,7 +128148,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128190
128148
  async function walk(pass, incoming, stored) {
128191
128149
  if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
128192
128150
  if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
128193
- if (!isRecord$3(incoming) || !isRecord$3(stored)) return incoming;
128151
+ if (!isRecord$4(incoming) || !isRecord$4(stored)) return incoming;
128194
128152
  const out = { ...incoming };
128195
128153
  for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
128196
128154
  return out;
@@ -128219,7 +128177,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128219
128177
  function isJsonEqual(a, b) {
128220
128178
  if (Object.is(a, b)) return true;
128221
128179
  if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
128222
- if (isRecord$3(a) && isRecord$3(b)) {
128180
+ if (isRecord$4(a) && isRecord$4(b)) {
128223
128181
  const keys = Object.keys(a);
128224
128182
  if (keys.length !== Object.keys(b).length) return false;
128225
128183
  return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
@@ -128241,7 +128199,7 @@ var require_sleep_gRQc2IoX = __commonJS({
128241
128199
  }
128242
128200
  function nodeFromStored(value, owner) {
128243
128201
  if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
128244
- if (!isRecord$3(value)) return null;
128202
+ if (!isRecord$4(value)) return null;
128245
128203
  const children = /* @__PURE__ */ new Map();
128246
128204
  for (const [key, child] of Object.entries(value)) {
128247
128205
  const node = nodeFromStored(child, owner);
@@ -130004,17 +129962,17 @@ var require_sleep_gRQc2IoX = __commonJS({
130004
129962
  }
130005
129963
  return prefixes;
130006
129964
  }
130007
- function isRecord$2(value) {
129965
+ function isRecord$3(value) {
130008
129966
  return typeof value === "object" && value !== null && !Array.isArray(value);
130009
129967
  }
130010
129968
  function elementId(element, idKey, declared, prefix) {
130011
- const id = isRecord$2(element) ? element[idKey] : void 0;
129969
+ const id = isRecord$3(element) ? element[idKey] : void 0;
130012
129970
  if (typeof id !== "string" || id.length === 0) throw new InvalidRecordError(`"${declared}": every element of "${prefix}" needs a non-empty string "${idKey}" to carry a secret`);
130013
129971
  return id;
130014
129972
  }
130015
129973
  var REMOVE_LEAF = /* @__PURE__ */ Symbol("remove-leaf");
130016
129974
  function mapAt(node, segments, index, walkedKeys, concretePrefix, declared, arrayKeys, visit) {
130017
- if (!isRecord$2(node)) return node;
129975
+ if (!isRecord$3(node)) return node;
130018
129976
  const segment = segments[index];
130019
129977
  if (segment === void 0) return node;
130020
129978
  if (!Object.prototype.hasOwnProperty.call(node, segment.key)) return node;
@@ -130220,7 +130178,7 @@ var require_sleep_gRQc2IoX = __commonJS({
130220
130178
  function declarationsOf(kinds) {
130221
130179
  return Object.fromEntries(Object.entries(kinds).map(([name, kind]) => [name, kind.declaration]));
130222
130180
  }
130223
- function isRecord$1(value) {
130181
+ function isRecord$2(value) {
130224
130182
  return typeof value === "object" && value !== null && !Array.isArray(value);
130225
130183
  }
130226
130184
  async function call(fn) {
@@ -130345,7 +130303,7 @@ var require_sleep_gRQc2IoX = __commonJS({
130345
130303
  }) : data;
130346
130304
  const parsed = this.def.schema.safeParse(shaped);
130347
130305
  if (!parsed.success) throw new InvalidRecordError(`${this.name}/${id}: ${zodSummary(parsed.error)}`);
130348
- if (!isRecord$1(parsed.data)) throw new InvalidRecordError(`${this.name}/${id}: the body must be an object`);
130306
+ if (!isRecord$2(parsed.data)) throw new InvalidRecordError(`${this.name}/${id}: the body must be an object`);
130349
130307
  return parsed.data;
130350
130308
  }
130351
130309
  async get(id) {
@@ -130514,7 +130472,7 @@ var require_sleep_gRQc2IoX = __commonJS({
130514
130472
  }
130515
130473
  };
130516
130474
  function toBody(value) {
130517
- if (!isRecord$1(value)) throw new InvalidRecordError("the record body must be an object");
130475
+ if (!isRecord$2(value)) throw new InvalidRecordError("the record body must be an object");
130518
130476
  return value;
130519
130477
  }
130520
130478
  function createRecordsAccess(options) {
@@ -130586,11 +130544,213 @@ var require_sleep_gRQc2IoX = __commonJS({
130586
130544
  if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
130587
130545
  return defined;
130588
130546
  }
130547
+ function isRecord$1(value) {
130548
+ return typeof value === "object" && value !== null && !Array.isArray(value);
130549
+ }
130550
+ function extractField(data, path) {
130551
+ let current = data;
130552
+ for (const segment of path.split(".")) {
130553
+ if (!isRecord$1(current)) return null;
130554
+ current = current[segment];
130555
+ }
130556
+ if (current === void 0 || current === null) return null;
130557
+ if (typeof current === "boolean") return current ? 1 : 0;
130558
+ if (typeof current === "number" || typeof current === "string") return current;
130559
+ return JSON.stringify(current);
130560
+ }
130561
+ function bindable(value) {
130562
+ if (typeof value === "boolean") return value ? 1 : 0;
130563
+ if (typeof value === "string" || typeof value === "number") return value;
130564
+ throw new InvalidRecordError("a where value must be a string, number or boolean");
130565
+ }
130566
+ function compareText(a, b) {
130567
+ const ai = a[Symbol.iterator]();
130568
+ const bi = b[Symbol.iterator]();
130569
+ for (; ; ) {
130570
+ const x = ai.next();
130571
+ const y = bi.next();
130572
+ if (x.done === true) return y.done === true ? 0 : -1;
130573
+ if (y.done === true) return 1;
130574
+ const cx = x.value.codePointAt(0) ?? 0;
130575
+ const cy = y.value.codePointAt(0) ?? 0;
130576
+ if (cx !== cy) return cx < cy ? -1 : 1;
130577
+ }
130578
+ }
130579
+ function compareSql(a, b) {
130580
+ if (a === null || b === null) return a === b ? 0 : a === null ? -1 : 1;
130581
+ if (typeof a === "number" && typeof b === "number") return a === b ? 0 : a < b ? -1 : 1;
130582
+ if (typeof a === "number") return -1;
130583
+ if (typeof b === "number") return 1;
130584
+ return compareText(a, b);
130585
+ }
130586
+ function rowValueAfter(row, cursor, desc) {
130587
+ for (let i = 0; i < row.length; i += 1) {
130588
+ const a = row[i] ?? null;
130589
+ const b = cursor[i] ?? null;
130590
+ if (a === null || b === null) return false;
130591
+ const c = compareSql(a, b);
130592
+ if (c !== 0) return desc ? c < 0 : c > 0;
130593
+ }
130594
+ return false;
130595
+ }
130596
+ function predicateOf(field, value) {
130597
+ if (typeof value === "object") return {
130598
+ field,
130599
+ shape: "in" in value ? "in" : "range",
130600
+ value
130601
+ };
130602
+ return {
130603
+ field,
130604
+ shape: "eq",
130605
+ value
130606
+ };
130607
+ }
130608
+ function predicateTest(p) {
130609
+ const value = p.value;
130610
+ if (p.shape === "eq") {
130611
+ const wanted = bindable(value);
130612
+ return (data) => {
130613
+ const got = extractField(data, p.field);
130614
+ return got !== null && compareSql(got, wanted) === 0;
130615
+ };
130616
+ }
130617
+ if (typeof value === "object" && "in" in value) {
130618
+ const set = value.in.map(bindable);
130619
+ return (data) => {
130620
+ const got = extractField(data, p.field);
130621
+ return got !== null && set.some((w) => w !== null && compareSql(got, w) === 0);
130622
+ };
130623
+ }
130624
+ if (typeof value !== "object") return () => false;
130625
+ const active = [
130626
+ ["gt" in value ? value.gt : void 0, (c) => c > 0],
130627
+ ["gte" in value ? value.gte : void 0, (c) => c >= 0],
130628
+ ["lt" in value ? value.lt : void 0, (c) => c < 0],
130629
+ ["lte" in value ? value.lte : void 0, (c) => c <= 0]
130630
+ ].flatMap(([b, ok]) => b === void 0 ? [] : [{
130631
+ bound: bindable(b),
130632
+ ok
130633
+ }]);
130634
+ return (data) => {
130635
+ const got = extractField(data, p.field);
130636
+ if (got === null) return false;
130637
+ return active.every(({ bound, ok }) => ok(compareSql(got, bound)));
130638
+ };
130639
+ }
130640
+ function planWhere(kind, decl, where, opts) {
130641
+ const predicates = Object.entries(where ?? {}).map(([f, v]) => predicateOf(f, v));
130642
+ const extra = opts.extraFields ?? [];
130643
+ if (predicates.length === 0 && extra.length === 0) return null;
130644
+ const equalities = predicates.filter((p) => p.shape !== "range");
130645
+ const ranges = predicates.filter((p) => p.shape === "range");
130646
+ if (ranges.length > 1) throw new UnindexedFilterError(`${kind}: at most one range predicate (${ranges.map((r) => r.field).join(", ")}) - it must be the field right after the equality fields of one index`);
130647
+ if (!opts.allowIn && equalities.some((p) => p.shape === "in")) throw new UnindexedFilterError(`${kind}: an "in" set cannot be paged in index order - ask once per value`);
130648
+ const eqCount = equalities.length;
130649
+ const eqSet = new Set(equalities.map((p) => p.field));
130650
+ const range = ranges[0];
130651
+ const candidates = decl.indexes.filter((index) => {
130652
+ const leading = index.fields.slice(0, eqCount);
130653
+ if (leading.length !== eqCount || !leading.every((f) => eqSet.has(f))) return false;
130654
+ if (range !== void 0 && index.fields[eqCount] !== range.field) return false;
130655
+ return extra.every((f) => index.fields.includes(f));
130656
+ });
130657
+ const groupBy = opts.groupBy;
130658
+ const candidate = (groupBy === void 0 ? void 0 : candidates.find((index) => index.fields[eqCount] === groupBy)) ?? candidates[0];
130659
+ if (candidate === void 0) {
130660
+ const declared = decl.indexes.map((i) => `${i.name}(${i.fields.join(", ")})`).join("; ");
130661
+ throw new UnindexedFilterError(`${kind}: no declared index serves [${[...predicates.map((p) => p.field), ...extra].join(", ")}]. Declared: ${declared.length > 0 ? declared : "none"}. A filter on an unindexed field does not compile - declare an index`);
130662
+ }
130663
+ const tests = predicates.map(predicateTest);
130664
+ return {
130665
+ indexName: candidate.name,
130666
+ orderFields: candidate.fields.slice(eqCount),
130667
+ matches: (data) => tests.every((t) => t(data))
130668
+ };
130669
+ }
130670
+ function assertWindowAllowed(kind, decl, w) {
130671
+ if (w.deviceId !== void 0 && decl.device === "none") throw new InvalidRecordError(`${kind}: declared device: "none", it cannot be filtered by deviceId`);
130672
+ if ((w.atFrom !== void 0 || w.atTo !== void 0) && decl.at === "none") throw new InvalidRecordError(`${kind}: declared at: "none", it cannot be filtered by time`);
130673
+ }
130674
+ function inWindow(row, w) {
130675
+ if (w.deviceId !== void 0 && row.deviceId !== w.deviceId) return false;
130676
+ if (w.atFrom !== void 0 && (row.at === null || row.at < w.atFrom)) return false;
130677
+ if (w.atTo !== void 0 && (row.at === null || row.at >= w.atTo)) return false;
130678
+ return true;
130679
+ }
130589
130680
  function isRecord(value) {
130590
130681
  return typeof value === "object" && value !== null && !Array.isArray(value);
130591
130682
  }
130683
+ function validateHeader(kind, decl, rec, nowMs) {
130684
+ const fail = (why) => {
130685
+ throw new InvalidRecordError(`${kind}/${rec.id.slice(0, 64)}: ${why}`);
130686
+ };
130687
+ if (rec.id.length === 0 || rec.id.length > 256) fail(`the id must be 1..256 characters`);
130688
+ if (decl.device === "required" && rec.deviceId === void 0) fail("deviceId is required");
130689
+ if (decl.device === "none" && rec.deviceId !== void 0) fail("this kind is not device-scoped");
130690
+ if (decl.at === "required" && rec.at === void 0) fail("at is required");
130691
+ if (decl.at === "none" && rec.at !== void 0) fail("this kind has no time");
130692
+ const { retention } = decl;
130693
+ let expiresAt = rec.expiresAt ?? null;
130694
+ if ("ttlMs" in retention) {
130695
+ if (rec.expiresAt !== void 0) fail("expiresAt is set by the engine on a kind with a ttl retention");
130696
+ expiresAt = (retention.from === "at" ? rec.at ?? nowMs : nowMs) + retention.ttlMs;
130697
+ } else if (rec.expiresAt !== void 0 && decl.secretPaths.length > 0) fail("a kind with secret fields cannot expire by the engine (its keychain values would be orphaned)");
130698
+ return {
130699
+ id: rec.id,
130700
+ deviceId: rec.deviceId ?? null,
130701
+ at: rec.at ?? null,
130702
+ expiresAt
130703
+ };
130704
+ }
130705
+ function serializeBody(kind, decl, id, body) {
130706
+ const json = JSON.stringify(body);
130707
+ const bytes = Buffer.byteLength(json, "utf8");
130708
+ if (bytes > decl.maxDataBytes) throw new RecordTooLargeError(`${kind}/${id.slice(0, 64)}: ${bytes} bytes exceeds maxDataBytes ${decl.maxDataBytes}. Bytes are never record fields - use files and ctx.peerBytes`);
130709
+ return json;
130710
+ }
130711
+ function markersOf(decl, body) {
130712
+ const out = /* @__PURE__ */ new Map();
130713
+ if (decl.secretPaths.length === 0) return out;
130714
+ for (const leaf of collectSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys)) if (isSecretMarker(leaf.value)) out.set(leaf.concrete, leaf.value.$secret);
130715
+ return out;
130716
+ }
130717
+ function redactBody(decl, body) {
130718
+ if (decl.secretPaths.length === 0) return body;
130719
+ const redacted = mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => leaf.value === null ? null : REDACTED_SECRET);
130720
+ return isRecord(redacted) ? redacted : body;
130721
+ }
130722
+ function enforceSecrets(owner, kind, decl, id, body, stored, mode) {
130723
+ if (decl.secretPaths.length === 0) return {
130724
+ body,
130725
+ releasedRefs: []
130726
+ };
130727
+ const storedMarkers = stored === null ? /* @__PURE__ */ new Map() : markersOf(decl, stored);
130728
+ const next = mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
130729
+ const expected = recordSecretRef(owner, kind, id, leaf.concrete);
130730
+ if (isSecretMarker(leaf.value)) {
130731
+ if (leaf.value.$secret !== expected) throw new ForeignSecretMarkerError(`${kind}/${id.slice(0, 64)} field "${leaf.concrete}": the marker is not this row's own ref`);
130732
+ return leaf.value;
130733
+ }
130734
+ if (leaf.value === "__camstack_redacted__") {
130735
+ const keep = storedMarkers.get(leaf.concrete);
130736
+ if (keep === void 0) return REMOVE_LEAF;
130737
+ if (mode === "patch" && !leaf.concrete.includes("[")) return REMOVE_LEAF;
130738
+ return {
130739
+ $secret: keep,
130740
+ v: 1
130741
+ };
130742
+ }
130743
+ if (leaf.value === null || leaf.value === void 0) return mode === "patch" ? null : REMOVE_LEAF;
130744
+ throw new PlaintextSecretError(`${kind}/${id.slice(0, 64)} field "${leaf.concrete}": a secret field takes a keychain marker, never a value`);
130745
+ });
130746
+ if (!isRecord(next)) throw new InvalidRecordError(`${kind}/${id}: the body must be an object`);
130747
+ const nextMarkers = markersOf(decl, next);
130748
+ return {
130749
+ body: next,
130750
+ releasedRefs: [...storedMarkers.entries()].filter(([path, ref]) => mode === "put" && nextMarkers.get(path) !== ref).map(([, ref]) => ref)
130751
+ };
130752
+ }
130592
130753
  function mergePatch(target, patch) {
130593
- if (!isRecord(patch)) return target;
130594
130754
  const out = { ...target };
130595
130755
  for (const [key, value] of Object.entries(patch)) {
130596
130756
  if (value === null) {
@@ -130598,17 +130758,14 @@ var require_sleep_gRQc2IoX = __commonJS({
130598
130758
  continue;
130599
130759
  }
130600
130760
  const current = out[key];
130601
- out[key] = isRecord(value) && isRecord(current) ? mergePatch(current, value) : value;
130761
+ out[key] = isRecord(value) ? mergePatch(isRecord(current) ? current : {}, value) : value;
130602
130762
  }
130603
130763
  return out;
130604
130764
  }
130605
- function markersOf(decl, body) {
130606
- const out = /* @__PURE__ */ new Map();
130607
- mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
130608
- if (isSecretMarker(leaf.value)) out.set(leaf.concrete, leaf.value.$secret);
130609
- return leaf.value;
130610
- });
130611
- return out;
130765
+ function jsonCopy(body) {
130766
+ const parsed = JSON.parse(JSON.stringify(body));
130767
+ if (!isRecord(parsed)) throw new InvalidRecordError("a stored body is not an object");
130768
+ return parsed;
130612
130769
  }
130613
130770
  function makeSpecKeychain(owner) {
130614
130771
  const values = /* @__PURE__ */ new Map();
@@ -130645,10 +130802,85 @@ var require_sleep_gRQc2IoX = __commonJS({
130645
130802
  forOwner: null
130646
130803
  } };
130647
130804
  }
130648
- function makeInMemoryRecords(owner = "spec") {
130805
+ function encodeCursor(tag, values) {
130806
+ return Buffer.from(JSON.stringify({
130807
+ t: tag,
130808
+ v: values
130809
+ }), "utf8").toString("base64url");
130810
+ }
130811
+ function decodeCursor(cursor) {
130812
+ try {
130813
+ const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
130814
+ if (typeof parsed === "object" && parsed !== null) {
130815
+ const t = Reflect.get(parsed, "t");
130816
+ const v = Reflect.get(parsed, "v");
130817
+ if (typeof t === "string" && Array.isArray(v)) {
130818
+ const values = [];
130819
+ for (const item of v) if (typeof item === "string" || typeof item === "number" || item === null) values.push(item);
130820
+ else throw new Error("bad cursor value");
130821
+ return {
130822
+ tag: t,
130823
+ values
130824
+ };
130825
+ }
130826
+ }
130827
+ } catch {
130828
+ }
130829
+ throw new InvalidRecordError("the cursor is not valid");
130830
+ }
130831
+ function assertCursor(cursor, tag, length) {
130832
+ if (cursor.tag !== tag || cursor.values.length !== length) throw new InvalidRecordError("the cursor does not belong to this query");
130833
+ }
130834
+ function compareKeys(a, b) {
130835
+ for (let i = 0; i < a.length; i += 1) {
130836
+ const c = compareSql(a[i] ?? null, b[i] ?? null);
130837
+ if (c !== 0) return c;
130838
+ }
130839
+ return 0;
130840
+ }
130841
+ function assertAdditive(kind, before, next) {
130842
+ const refuse = (why) => {
130843
+ throw new DeclarationRefusedError(`kind "${kind}": ${why} - the engine never migrates data; a changed index is a new name`);
130844
+ };
130845
+ if (before.database !== next.database) refuse("the database cannot change");
130846
+ if (before.device !== next.device) refuse('"device" cannot change');
130847
+ if (before.at !== next.at) refuse('"at" cannot change');
130848
+ for (const old of before.indexes) {
130849
+ const same = next.indexes.find((i) => i.name === old.name);
130850
+ if (same === void 0) continue;
130851
+ if (same.unique !== old.unique || same.fields.join(",") !== old.fields.join(",")) refuse(`index "${old.name}" was declared differently before`);
130852
+ }
130853
+ for (const path of before.secretPaths) if (!next.secretPaths.includes(path)) refuse(`secret path "${path}" cannot stop being secret`);
130854
+ }
130855
+ function ringBounds(decl) {
130856
+ const { retention } = decl;
130857
+ if ("maxRows" in retention || "maxRowsPerDevice" in retention) return {
130858
+ ...retention.maxRows === void 0 ? {} : { maxRows: retention.maxRows },
130859
+ ...retention.maxRowsPerDevice === void 0 ? {} : { maxRowsPerDevice: retention.maxRowsPerDevice }
130860
+ };
130861
+ return null;
130862
+ }
130863
+ var HISTOGRAM_MAX_BUCKETS = 1e4;
130864
+ function aggregateOf(op, field, rows) {
130865
+ if (field === void 0) return rows.length;
130866
+ const values = rows.map((r) => extractField(r.data, field)).filter((v) => v !== null);
130867
+ if (op === "count") return values.length;
130868
+ if (values.length === 0) return null;
130869
+ if (op === "sum") return values.reduce((s, v) => s + (typeof v === "number" ? v : Number(v) || 0), 0);
130870
+ const sorted = [...values].sort(compareSql);
130871
+ const picked = op === "min" ? sorted[0] : sorted.at(-1);
130872
+ return typeof picked === "number" ? picked : null;
130873
+ }
130874
+ function makeInMemoryRecords(owner = "spec", options = {}) {
130875
+ const now = options.now ?? Date.now;
130649
130876
  const decls = /* @__PURE__ */ new Map();
130877
+ const kindIds = /* @__PURE__ */ new Map();
130650
130878
  const tables = /* @__PURE__ */ new Map();
130651
- let clock = 1;
130879
+ const sequences = /* @__PURE__ */ new Map();
130880
+ const pendingAllocated = /* @__PURE__ */ new Set();
130881
+ const writesSinceTrim = /* @__PURE__ */ new Map();
130882
+ const queries = [];
130883
+ let nextRid = 1;
130652
130884
  let writesFail = false;
130653
130885
  let readsFail = false;
130654
130886
  const table = (kind) => {
@@ -130661,74 +130893,107 @@ var require_sleep_gRQc2IoX = __commonJS({
130661
130893
  };
130662
130894
  const declOf = (kind) => {
130663
130895
  const decl = decls.get(kind);
130664
- if (decl === void 0) throw new Error(`kind "${kind}" is not declared`);
130896
+ if (decl === void 0) throw new UnknownRecordKindError(`"${owner}" declared no kind "${kind}"`);
130665
130897
  return decl;
130666
130898
  };
130667
- const redact = (decl, body) => {
130668
- if (decl.secretPaths.length === 0) return body;
130669
- const out = mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => leaf.value === null ? null : REDACTED_SECRET);
130670
- return isRecord(out) ? out : body;
130899
+ const reading = () => {
130900
+ if (readsFail) throw new Error("records engine unreachable");
130901
+ };
130902
+ const writing = () => {
130903
+ if (writesFail) throw new Error("records engine unreachable");
130671
130904
  };
130672
- const view = (kind, row) => ({
130905
+ const view = (decl, row) => ({
130673
130906
  id: row.id,
130674
- deviceId: null,
130907
+ deviceId: row.deviceId,
130675
130908
  at: row.at,
130676
- expiresAt: null,
130909
+ expiresAt: row.expiresAt,
130677
130910
  rev: row.rev,
130678
130911
  updatedAt: row.updatedAt,
130679
- data: redact(declOf(kind), row.data)
130912
+ data: redactBody(decl, jsonCopy(row.data))
130680
130913
  });
130681
- const enforce = (kind, id, body, stored) => {
130682
- const decl = declOf(kind);
130683
- if (decl.secretPaths.length === 0) return {
130684
- body,
130685
- released: []
130686
- };
130687
- const before = stored === null ? /* @__PURE__ */ new Map() : markersOf(decl, stored);
130688
- const next = mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
130689
- const expected = recordSecretRef(owner, kind, id, leaf.concrete);
130690
- if (isSecretMarker(leaf.value)) {
130691
- if (leaf.value.$secret !== expected) throw new Error("foreign secret marker");
130692
- return leaf.value;
130693
- }
130694
- if (leaf.value === "__camstack_redacted__") {
130695
- const keep = before.get(leaf.concrete);
130696
- return keep === void 0 ? REMOVE_LEAF : {
130697
- $secret: keep,
130698
- v: 1
130699
- };
130914
+ const assertUnique = (kind, decl, id, body) => {
130915
+ for (const index of decl.indexes) {
130916
+ if (index.unique !== true) continue;
130917
+ const mine = index.fields.map((f) => extractField(body, f));
130918
+ if (mine.some((v) => v === null)) continue;
130919
+ for (const other of table(kind).values()) {
130920
+ if (other.id === id) continue;
130921
+ const theirs = index.fields.map((f) => extractField(other.data, f));
130922
+ if (compareKeys(mine, theirs) === 0 && theirs.every((v) => v !== null)) throw new RecordUniqueViolationError(`${kind}: the unique index "${index.name}" refused the write`);
130700
130923
  }
130701
- if (leaf.value === null || leaf.value === void 0) return REMOVE_LEAF;
130702
- throw new Error(`${kind}/${id}: a secret field takes a keychain marker, never a value`);
130924
+ }
130925
+ };
130926
+ const store2 = (kind, prev, next) => {
130927
+ const rid = prev?.rid ?? nextRid;
130928
+ if (prev === void 0) nextRid += 1;
130929
+ table(kind).set(next.id, {
130930
+ ...next,
130931
+ rid
130703
130932
  });
130704
- if (!isRecord(next)) throw new Error("the body must be an object");
130705
- const after = markersOf(decl, next);
130706
- return {
130707
- body: next,
130708
- released: [...before.entries()].filter(([p, ref]) => after.get(p) !== ref).map(([, r]) => r)
130709
- };
130710
130933
  };
130711
- const write = (kind, input) => {
130712
- if (writesFail) throw new Error("records engine unreachable");
130713
- if (declOf(kind).at === "required" && input.at === void 0) throw new Error(`${kind}/${input.id}: the kind needs "at" on every write`);
130714
- const prev = table(kind).get(input.id);
130715
- const { body, released } = enforce(kind, input.id, input.data, prev?.data ?? null);
130934
+ const writeRecord = (kind, rec, ifRev, nowMs) => {
130935
+ const decl = declOf(kind);
130936
+ const header = validateHeader(kind, decl, rec, nowMs);
130937
+ const allocatedKey = `${kind}:${rec.id}`;
130938
+ const prev = table(kind).get(rec.id);
130939
+ if (pendingAllocated.has(allocatedKey) && prev !== void 0) throw new RevConflictError(`${kind}/${rec.id}: an allocated id is insert-only and a row already holds it`);
130940
+ if (ifRev !== void 0) {
130941
+ if (ifRev === 0 && prev !== void 0) throw new RevConflictError(`${kind}/${rec.id}: the row exists (ifRev 0 means "must not exist")`);
130942
+ if (ifRev > 0 && prev?.rev !== ifRev) throw new RevConflictError(`${kind}/${rec.id}: expected rev ${ifRev}, found ${prev === void 0 ? "no row" : `rev ${prev.rev}`}`);
130943
+ }
130944
+ const checked = enforceSecrets(owner, kind, decl, rec.id, rec.data, prev?.data ?? null, "put");
130945
+ serializeBody(kind, decl, rec.id, checked.body);
130946
+ const body = jsonCopy(checked.body);
130947
+ assertUnique(kind, decl, rec.id, body);
130716
130948
  const rev = (prev?.rev ?? 0) + 1;
130717
- clock += 1;
130718
- table(kind).set(input.id, {
130719
- id: input.id,
130720
- at: input.at ?? null,
130949
+ store2(kind, prev, {
130950
+ id: header.id,
130951
+ deviceId: header.deviceId,
130952
+ at: header.at,
130953
+ expiresAt: header.expiresAt,
130721
130954
  rev,
130722
- updatedAt: clock,
130955
+ updatedAt: nowMs,
130723
130956
  data: body
130724
130957
  });
130958
+ pendingAllocated.delete(allocatedKey);
130725
130959
  return {
130726
130960
  rev,
130727
- released
130961
+ released: checked.releasedRefs
130728
130962
  };
130729
130963
  };
130730
- const unimplemented = (op) => {
130731
- throw new Error(`the fake records transport does not implement ${op}`);
130964
+ const trimScope = (kind, max, deviceId) => {
130965
+ const scope = [...table(kind).values()].filter((r) => deviceId === void 0 || r.deviceId === deviceId);
130966
+ const excess = Math.min(scope.length - max, RECORD_DELETE_BATCH);
130967
+ if (excess <= 0) return;
130968
+ scope.sort((a, b) => compareKeys([a.at, a.rid], [b.at, b.rid]));
130969
+ for (const row of scope.slice(0, excess)) table(kind).delete(row.id);
130970
+ };
130971
+ const afterWrite = (kind, devices) => {
130972
+ const bounds = ringBounds(declOf(kind));
130973
+ if (bounds === null) return;
130974
+ const bound = Math.max(bounds.maxRows ?? 0, bounds.maxRowsPerDevice ?? 0);
130975
+ const interval = bound <= 100 ? 1 : Math.floor(bound / 100);
130976
+ const count = (writesSinceTrim.get(kind) ?? 0) + devices.length;
130977
+ if (count < interval) {
130978
+ writesSinceTrim.set(kind, count);
130979
+ return;
130980
+ }
130981
+ writesSinceTrim.set(kind, 0);
130982
+ if (bounds.maxRows !== void 0) trimScope(kind, bounds.maxRows, void 0);
130983
+ if (bounds.maxRowsPerDevice !== void 0) {
130984
+ const seen = new Set(devices.filter((d) => d !== void 0));
130985
+ for (const device of seen) trimScope(kind, bounds.maxRowsPerDevice, device);
130986
+ }
130987
+ };
130988
+ const refsOf = (decl, rows) => rows.flatMap((row) => [...markersOf(decl, row.data).values()]);
130989
+ const removeWhere = (kind, test) => {
130990
+ const decl = declOf(kind);
130991
+ const gone = [...table(kind).values()].filter(test);
130992
+ for (const row of gone) table(kind).delete(row.id);
130993
+ return {
130994
+ deleted: gone.length,
130995
+ secretRefs: refsOf(decl, gone)
130996
+ };
130732
130997
  };
130733
130998
  return {
130734
130999
  records: createRecordsAccess({
@@ -130736,69 +131001,119 @@ var require_sleep_gRQc2IoX = __commonJS({
130736
131001
  transport: {
130737
131002
  declareKinds: async ({ kinds }) => {
130738
131003
  const out = {};
130739
- let n = 0;
130740
- for (const [name, decl] of Object.entries(kinds)) {
131004
+ for (const [name, raw] of Object.entries(kinds)) {
131005
+ const decl = RecordKindDeclarationSchema.parse(raw);
131006
+ assertValidDeclaration(name, decl);
131007
+ const prior = decls.get(name);
131008
+ if (prior !== void 0) assertAdditive(name, prior, decl);
131009
+ const kindId = kindIds.get(name) ?? kindIds.size + 1;
131010
+ kindIds.set(name, kindId);
131011
+ const created = decl.indexes.filter((i) => prior?.indexes.every((p) => p.name !== i.name) ?? true).map((i) => i.name);
131012
+ const state = prior === void 0 ? "created" : JSON.stringify(prior) === JSON.stringify(decl) ? "unchanged" : "updated";
130741
131013
  decls.set(name, decl);
130742
- n += 1;
130743
131014
  out[name] = {
130744
- kindId: n,
130745
- state: "created",
130746
- createdIndexes: decl.indexes.map((i) => i.name),
131015
+ kindId,
131016
+ state,
131017
+ createdIndexes: created,
130747
131018
  adoptionPending: null
130748
131019
  };
130749
131020
  }
130750
131021
  return { kinds: out };
130751
131022
  },
130752
131023
  get: async ({ kind, id }) => {
130753
- if (readsFail) throw new Error("records engine unreachable");
131024
+ reading();
131025
+ const decl = declOf(kind);
130754
131026
  const row = table(kind).get(id);
130755
- return row === void 0 ? null : view(kind, row);
131027
+ return row === void 0 ? null : view(decl, row);
131028
+ },
131029
+ getMany: async ({ kind, ids }) => {
131030
+ reading();
131031
+ const decl = declOf(kind);
131032
+ return [...new Set(ids)].sort((a, b) => compareSql(a, b)).flatMap((id) => {
131033
+ const row = table(kind).get(id);
131034
+ return row === void 0 ? [] : [view(decl, row)];
131035
+ });
130756
131036
  },
130757
- getMany: async ({ kind, ids }) => ids.flatMap((id) => {
130758
- const row = table(kind).get(id);
130759
- return row === void 0 ? [] : [view(kind, row)];
130760
- }),
130761
131037
  secretRefs: async ({ kind, ids }) => {
131038
+ reading();
130762
131039
  const decl = declOf(kind);
130763
131040
  const out = {};
130764
131041
  for (const id of ids) {
130765
131042
  const row = table(kind).get(id);
130766
- if (row !== void 0) out[id] = Object.fromEntries(markersOf(decl, row.data));
131043
+ if (row === void 0) continue;
131044
+ const refs = Object.fromEntries(markersOf(decl, row.data));
131045
+ if (Object.keys(refs).length > 0) out[id] = refs;
130767
131046
  }
130768
131047
  return out;
130769
131048
  },
130770
131049
  put: async ({ kind, record, ifRev }) => {
130771
- if (ifRev !== void 0 && (table(kind).get(record.id)?.rev ?? 0) !== ifRev) throw new Error("stale ifRev");
130772
- const { rev, released } = write(kind, record);
131050
+ writing();
131051
+ const written = writeRecord(kind, record, ifRev, now());
131052
+ afterWrite(kind, [record.deviceId]);
130773
131053
  return {
130774
- rev,
130775
- releasedRefs: released
131054
+ rev: written.rev,
131055
+ releasedRefs: [...written.released]
130776
131056
  };
130777
131057
  },
130778
131058
  putMany: async ({ kind, records }) => {
131059
+ writing();
131060
+ declOf(kind);
131061
+ if (records.length > 1e3) throw new BatchTooLargeError(`${records.length} records exceed ${RECORD_BATCH_MAX}`);
131062
+ const bytes = records.reduce((sum, r) => sum + Buffer.byteLength(JSON.stringify(r.data), "utf8"), 0);
131063
+ if (bytes > 4194304) throw new BatchTooLargeError(`${bytes} bytes exceed ${RECORD_BATCH_MAX_BYTES}`);
131064
+ const nowMs = now();
131065
+ const before = new Map(table(kind));
131066
+ const ridBefore = nextRid;
130779
131067
  const released = [];
130780
- for (const record of records) released.push(...write(kind, record).released);
131068
+ try {
131069
+ for (const rec of records) released.push(...writeRecord(kind, rec, void 0, nowMs).released);
131070
+ } catch (err) {
131071
+ tables.set(kind, before);
131072
+ nextRid = ridBefore;
131073
+ throw err;
131074
+ }
131075
+ let top = -1;
131076
+ for (const r of records) if (/^\d{1,15}$/.test(r.id)) top = Math.max(top, Number(r.id));
131077
+ if (top >= 0) sequences.set(kind, Math.max(sequences.get(kind) ?? 0, top + 1));
131078
+ afterWrite(kind, records.map((r) => r.deviceId));
130781
131079
  return {
130782
131080
  count: records.length,
130783
131081
  releasedRefs: released
130784
131082
  };
130785
131083
  },
130786
- patch: async ({ kind, id, data, at, ifRev }) => {
130787
- const prev = table(kind).get(id);
130788
- if (prev === void 0) throw new Error(`${kind}/${id}: no such record`);
130789
- if (ifRev !== void 0 && prev.rev !== ifRev) throw new Error("stale ifRev");
130790
- const { rev, released } = write(kind, {
130791
- id,
130792
- ...at !== void 0 && at !== null ? { at } : prev.at !== null ? { at: prev.at } : {},
130793
- data: mergePatch(prev.data, data)
131084
+ patch: async (input) => {
131085
+ writing();
131086
+ const decl = declOf(input.kind);
131087
+ if (input.at !== void 0 && decl.at !== "required") throw new InvalidRecordError(`${input.kind}: declared at: "none"`);
131088
+ if (input.at === null) throw new InvalidRecordError(`${input.kind}: "at" cannot be removed`);
131089
+ if (input.expiresAt !== void 0 && decl.secretPaths.length > 0) throw new InvalidRecordError(`${input.kind}: a kind with secret fields cannot expire by the engine (its keychain values would be orphaned)`);
131090
+ if (input.expiresAt !== void 0 && "ttlMs" in decl.retention) throw new InvalidRecordError(`${input.kind}: expiresAt is set by the engine`);
131091
+ const before = table(input.kind).get(input.id);
131092
+ const checked = enforceSecrets(owner, input.kind, decl, input.id, input.data, before?.data ?? null, "patch");
131093
+ if (before === void 0) throw new RecordNotFoundError(`${input.kind}/${input.id}: no such row`);
131094
+ if (input.ifRev !== void 0 && before.rev !== input.ifRev) throw new RevConflictError(`${input.kind}/${input.id}: expected rev ${String(input.ifRev)}, found rev ${before.rev}`);
131095
+ const merged = jsonCopy(mergePatch(before.data, jsonCopy(checked.body)));
131096
+ const size = [...JSON.stringify(merged)].length;
131097
+ if (size > decl.maxDataBytes) throw new RecordTooLargeError(`${input.kind}/${input.id}: the patched body is ${size} bytes, over maxDataBytes ${decl.maxDataBytes}`);
131098
+ assertUnique(input.kind, decl, input.id, merged);
131099
+ const rev = before.rev + 1;
131100
+ store2(input.kind, before, {
131101
+ ...before,
131102
+ at: input.at ?? before.at,
131103
+ expiresAt: input.expiresAt === void 0 ? before.expiresAt : input.expiresAt,
131104
+ rev,
131105
+ updatedAt: now(),
131106
+ data: merged
130794
131107
  });
131108
+ const kept = new Set(markersOf(decl, merged).values());
130795
131109
  return {
130796
131110
  rev,
130797
- releasedRefs: released
131111
+ releasedRefs: [...markersOf(decl, before.data).values()].filter((r) => !kept.has(r))
130798
131112
  };
130799
131113
  },
130800
131114
  delete: async ({ kind, id }) => {
130801
- if (writesFail) throw new Error("records engine unreachable");
131115
+ writing();
131116
+ const decl = declOf(kind);
130802
131117
  const row = table(kind).get(id);
130803
131118
  if (row === void 0) return {
130804
131119
  deleted: false,
@@ -130807,57 +131122,189 @@ var require_sleep_gRQc2IoX = __commonJS({
130807
131122
  table(kind).delete(id);
130808
131123
  return {
130809
131124
  deleted: true,
130810
- secretRefs: [...markersOf(declOf(kind), row.data).values()]
131125
+ secretRefs: refsOf(decl, [row])
130811
131126
  };
130812
131127
  },
130813
131128
  deleteMany: async ({ kind, ids }) => {
130814
- let deleted = 0;
130815
- const refs = [];
130816
- for (const id of ids) {
130817
- const row = table(kind).get(id);
130818
- if (row === void 0) continue;
130819
- table(kind).delete(id);
130820
- deleted += 1;
130821
- refs.push(...markersOf(declOf(kind), row.data).values());
131129
+ writing();
131130
+ const wanted = new Set(ids);
131131
+ return removeWhere(kind, (row) => wanted.has(row.id));
131132
+ },
131133
+ query: async (q) => {
131134
+ reading();
131135
+ const decl = declOf(q.kind);
131136
+ queries.push({
131137
+ kind: q.kind,
131138
+ limit: q.limit
131139
+ });
131140
+ assertWindowAllowed(q.kind, decl, q);
131141
+ const desc = q.desc === true;
131142
+ const dir = desc ? "DESC" : "ASC";
131143
+ const where = planWhere(q.kind, decl, q.where, { allowIn: false });
131144
+ const cursor = q.cursor === void 0 ? void 0 : decodeCursor(q.cursor);
131145
+ let rows = [...table(q.kind).values()].filter((r) => inWindow(r, q));
131146
+ let keysOf;
131147
+ let keyCount;
131148
+ let tag;
131149
+ if (where !== null) {
131150
+ if (q.order !== void 0) throw new InvalidRecordError(`${q.kind}: with a where the order is the index's; drop "order"`);
131151
+ const fields = where.orderFields;
131152
+ keysOf = (row) => [...fields.map((f) => extractField(row.data, f)), row.rid];
131153
+ keyCount = fields.length;
131154
+ tag = `rx:${where.indexName}:${dir}`;
131155
+ rows = rows.filter((r) => where.matches(r.data));
131156
+ if (cursor !== void 0) {
131157
+ assertCursor(cursor, tag, fields.length + 1);
131158
+ rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
131159
+ }
131160
+ } else {
131161
+ const order = q.order ?? (decl.at === "required" ? "at" : "id");
131162
+ keyCount = 1;
131163
+ if (order === "at") {
131164
+ if (decl.at !== "required") throw new InvalidRecordError(`${q.kind}: declared at: "none", it has no time order - use order: "id"`);
131165
+ keysOf = (row) => [row.at, row.rid];
131166
+ tag = `at:${dir}`;
131167
+ if (cursor !== void 0) {
131168
+ assertCursor(cursor, tag, 2);
131169
+ rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
131170
+ }
131171
+ } else {
131172
+ if (q.deviceId !== void 0 || q.atFrom !== void 0 || q.atTo !== void 0) throw new UnindexedFilterError(`${q.kind}: order "id" cannot be combined with a device or time window (use order "at")`);
131173
+ keysOf = (row) => [row.id, row.rid];
131174
+ tag = `id:${dir}`;
131175
+ if (cursor !== void 0) {
131176
+ assertCursor(cursor, tag, 2);
131177
+ const last2 = cursor.values[0] ?? null;
131178
+ rows = rows.filter((r) => rowValueAfter([r.id], [last2], desc));
131179
+ }
131180
+ }
131181
+ }
131182
+ rows.sort((a, b) => (desc ? -1 : 1) * compareKeys(keysOf(a), keysOf(b)));
131183
+ const page = rows.slice(0, q.limit);
131184
+ const more = rows.length > q.limit;
131185
+ const last = page.at(-1);
131186
+ let nextCursor = null;
131187
+ if (more && last !== void 0) {
131188
+ const all = keysOf(last);
131189
+ const keys = [];
131190
+ for (let i = 0; i < keyCount; i += 1) {
131191
+ const value = all[i];
131192
+ if (typeof value !== "string" && typeof value !== "number") throw new InvalidRecordError(`${q.kind}: a row has no value for an ordering field, so this query cannot be paged`);
131193
+ keys.push(value);
131194
+ }
131195
+ keys.push(last.rid);
131196
+ nextCursor = encodeCursor(tag, keys);
130822
131197
  }
130823
131198
  return {
130824
- deleted,
130825
- secretRefs: refs
131199
+ records: page.map((r) => view(decl, r)),
131200
+ nextCursor
130826
131201
  };
130827
131202
  },
130828
- query: async (q) => {
130829
- if (readsFail) throw new Error("records engine unreachable");
131203
+ count: async (q) => {
131204
+ reading();
130830
131205
  const decl = declOf(q.kind);
130831
- const asked = Object.keys(q.where ?? {});
130832
- if (asked.length > 0) {
130833
- if (!decl.indexes.some((index) => {
130834
- const leading = new Set(index.fields.slice(0, asked.length));
130835
- return asked.length <= index.fields.length && asked.every((f) => leading.has(f));
130836
- })) throw new Error(`${q.kind}: no declared index serves [${asked.join(", ")}]`);
130837
- }
130838
- let rows = [...table(q.kind).values()];
130839
- for (const [field, wanted] of Object.entries(q.where ?? {})) rows = rows.filter((r) => r.data[field] === wanted);
130840
- const byAt = q.order === "at" || q.order === void 0 && decl.at === "required";
130841
- rows.sort((a, b) => byAt ? (a.at ?? 0) - (b.at ?? 0) : a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
130842
- if (q.desc === true) rows.reverse();
130843
- const start = q.cursor === void 0 ? 0 : Number(q.cursor);
130844
- const page = rows.slice(start, start + q.limit);
130845
- const more = start + q.limit < rows.length;
131206
+ assertWindowAllowed(q.kind, decl, q);
131207
+ const where = planWhere(q.kind, decl, q.where, { allowIn: true });
131208
+ let n = 0;
131209
+ for (const row of table(q.kind).values()) if (inWindow(row, q) && (where === null || where.matches(row.data))) n += 1;
131210
+ return { count: n };
131211
+ },
131212
+ histogram: async (q) => {
131213
+ reading();
131214
+ const decl = declOf(q.kind);
131215
+ assertWindowAllowed(q.kind, decl, {
131216
+ deviceId: q.deviceId,
131217
+ atFrom: q.from
131218
+ });
131219
+ if (!(q.to > q.from)) throw new InvalidRecordError(`${q.kind}: histogram needs from < to`);
131220
+ if (Math.ceil((q.to - q.from) / q.bucketMs) > 1e4) throw new InvalidRecordError(`${q.kind}: histogram would exceed ${HISTOGRAM_MAX_BUCKETS} buckets`);
131221
+ const from = Math.floor(q.from);
131222
+ const to = Math.ceil(q.to);
131223
+ const step = Math.trunc(q.bucketMs);
131224
+ const counts = /* @__PURE__ */ new Map();
131225
+ for (const row of table(q.kind).values()) {
131226
+ if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) continue;
131227
+ if (row.at === null || row.at < from || row.at >= to) continue;
131228
+ const b = Math.trunc((row.at - from) / step);
131229
+ counts.set(b, (counts.get(b) ?? 0) + 1);
131230
+ }
131231
+ return { buckets: [...counts.entries()].sort(([a], [b]) => a - b).map(([b, count]) => ({
131232
+ bucketStart: from + b * q.bucketMs,
131233
+ count
131234
+ })) };
131235
+ },
131236
+ aggregate: async (q) => {
131237
+ reading();
131238
+ const decl = declOf(q.kind);
131239
+ if (q.op !== "count" && q.field === void 0) throw new InvalidRecordError(`${q.kind}: ${q.op} needs a field`);
131240
+ const extra = [q.field, q.groupBy].filter((f) => f !== void 0);
131241
+ if (extra.length === 0 && q.where === void 0) throw new InvalidRecordError(`${q.kind}: a count with no field and no groupBy is "count"`);
131242
+ const where = planWhere(q.kind, decl, q.where, {
131243
+ allowIn: true,
131244
+ extraFields: extra,
131245
+ groupBy: q.groupBy
131246
+ });
131247
+ if (where === null) throw new InvalidRecordError(`${q.kind}: aggregate has nothing to read`);
131248
+ const rows = [...table(q.kind).values()].filter((r) => where.matches(r.data));
131249
+ const groups = /* @__PURE__ */ new Map();
131250
+ if (q.groupBy === void 0) groups.set(null, rows);
131251
+ else {
131252
+ const by = q.groupBy;
131253
+ for (const row of rows) {
131254
+ const g = extractField(row.data, by);
131255
+ groups.set(g, [...groups.get(g) ?? [], row]);
131256
+ }
131257
+ }
131258
+ return { rows: [...groups.entries()].sort(([a], [b]) => compareSql(a, b)).map(([group, members]) => ({
131259
+ group,
131260
+ value: aggregateOf(q.op, q.field, members)
131261
+ })) };
131262
+ },
131263
+ deleteWhere: async (q) => {
131264
+ writing();
131265
+ const decl = declOf(q.kind);
131266
+ if (q.deviceId === void 0 && q.atBefore === void 0 && (q.where === void 0 || Object.keys(q.where).length === 0)) throw new FilterRequiredError(`${q.kind}: deleteWhere needs deviceId, atBefore or where - there is no "delete all"`);
131267
+ assertWindowAllowed(q.kind, decl, {
131268
+ deviceId: q.deviceId,
131269
+ atFrom: q.atBefore
131270
+ });
131271
+ const where = planWhere(q.kind, decl, q.where, { allowIn: true });
131272
+ return removeWhere(q.kind, (row) => {
131273
+ if (where !== null && !where.matches(row.data)) return false;
131274
+ if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) return false;
131275
+ if (q.atBefore !== void 0 && (row.at === null || row.at >= q.atBefore)) return false;
131276
+ return true;
131277
+ });
131278
+ },
131279
+ deleteDevice: async ({ deviceId, kinds }) => {
131280
+ writing();
131281
+ const deleted = {};
131282
+ const secretRefs = [];
131283
+ for (const [kind, decl] of decls) {
131284
+ if (decl.deviceRemoval !== "delete") continue;
131285
+ if (kinds !== void 0 && !kinds.includes(kind)) continue;
131286
+ const result = removeWhere(kind, (row) => row.deviceId === deviceId);
131287
+ deleted[kind] = result.deleted;
131288
+ secretRefs.push(...result.secretRefs);
131289
+ }
130846
131290
  return {
130847
- records: page.map((r) => view(q.kind, r)),
130848
- nextCursor: more ? String(start + q.limit) : null
131291
+ deleted,
131292
+ secretRefs
130849
131293
  };
130850
131294
  },
130851
- count: async ({ kind }) => ({ count: table(kind).size }),
130852
- histogram: async () => unimplemented("histogram"),
130853
- aggregate: async () => unimplemented("aggregate"),
130854
- deleteWhere: async () => unimplemented("deleteWhere"),
130855
- deleteDevice: async () => unimplemented("deleteDevice"),
130856
- allocateId: async () => unimplemented("allocateId")
131295
+ allocateId: async ({ kind }) => {
131296
+ writing();
131297
+ declOf(kind);
131298
+ const id = sequences.get(kind) ?? 1;
131299
+ sequences.set(kind, id + 1);
131300
+ pendingAllocated.add(`${kind}:${id}`);
131301
+ return { id };
131302
+ }
130857
131303
  },
130858
131304
  secrets: makeSpecKeychain(owner).access
130859
131305
  }),
130860
131306
  tables,
131307
+ queries,
130861
131308
  failWrites: (on) => {
130862
131309
  writesFail = on;
130863
131310
  },
@@ -130865,12 +131312,14 @@ var require_sleep_gRQc2IoX = __commonJS({
130865
131312
  readsFail = on;
130866
131313
  },
130867
131314
  seed: (kind, row) => {
130868
- table(kind).set(row.id, {
131315
+ store2(kind, table(kind).get(row.id), {
130869
131316
  id: row.id,
131317
+ deviceId: row.deviceId ?? null,
130870
131318
  at: row.at ?? null,
131319
+ expiresAt: row.expiresAt ?? null,
130871
131320
  rev: 1,
130872
131321
  updatedAt: 1,
130873
- data: row.data
131322
+ data: jsonCopy(row.data)
130874
131323
  });
130875
131324
  }
130876
131325
  };
@@ -134634,7 +135083,7 @@ var require_addon = __commonJS({
134634
135083
  "../types/dist/addon.js"(exports) {
134635
135084
  "use strict";
134636
135085
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
134637
- var require_sleep = require_sleep_gRQc2IoX();
135086
+ var require_sleep = require_sleep_Re8daN0Y();
134638
135087
  var require_event_category = require_event_category_eSqkye_K();
134639
135088
  var require_err_msg = require_err_msg_BhVbr0NX();
134640
135089
  var CAP_INPUT_DEFAULTS = Object.freeze({
@@ -136984,9 +137433,9 @@ var require_addon = __commonJS({
136984
137433
  }
136985
137434
  });
136986
137435
 
136987
- // ../system/dist/retired-settings-keys-D_VwZiDt.js
136988
- var require_retired_settings_keys_D_VwZiDt = __commonJS({
136989
- "../system/dist/retired-settings-keys-D_VwZiDt.js"(exports) {
137436
+ // ../system/dist/retired-settings-keys-CGUqX-Oz.js
137437
+ var require_retired_settings_keys_CGUqX_Oz = __commonJS({
137438
+ "../system/dist/retired-settings-keys-CGUqX-Oz.js"(exports) {
136990
137439
  "use strict";
136991
137440
  var _camstack_types_addon = require_addon();
136992
137441
  function settingsStoreIsAuthoritativeHere(env) {
@@ -137247,12 +137696,6 @@ var require_retired_settings_keys_D_VwZiDt = __commonJS({
137247
137696
  function errText(err) {
137248
137697
  return err instanceof Error ? err.message : String(err);
137249
137698
  }
137250
- Object.defineProperty(exports, "RETIRED_SETTINGS_KEYS", {
137251
- enumerable: true,
137252
- get: function() {
137253
- return RETIRED_SETTINGS_KEYS;
137254
- }
137255
- });
137256
137699
  Object.defineProperty(exports, "purgeRetiredSettingsKeys", {
137257
137700
  enumerable: true,
137258
137701
  get: function() {
@@ -137283,11 +137726,11 @@ var require_device_manager_addon = __commonJS({
137283
137726
  [Symbol.toStringTag]: { value: "Module" }
137284
137727
  });
137285
137728
  require_chunk_Cek0wNdY();
137286
- var require_dist10 = require_dist_Bn_RNanh();
137729
+ var require_dist10 = require_dist_D9aw_d0G();
137287
137730
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
137288
137731
  var require_prefix_range = require_prefix_range_D_KueXbQ();
137289
137732
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
137290
- var require_retired_settings_keys = require_retired_settings_keys_D_VwZiDt();
137733
+ var require_retired_settings_keys = require_retired_settings_keys_CGUqX_Oz();
137291
137734
  var zod = require_zod();
137292
137735
  var node_crypto = __require("crypto");
137293
137736
  var _camstack_types_node = require_node();
@@ -146355,7 +146798,7 @@ var require_hub_forwarder = __commonJS({
146355
146798
  [Symbol.toStringTag]: { value: "Module" }
146356
146799
  });
146357
146800
  require_chunk_Cek0wNdY();
146358
- var require_dist10 = require_dist_Bn_RNanh();
146801
+ var require_dist10 = require_dist_D9aw_d0G();
146359
146802
  var require_formatter = require_formatter_DqAKDlvN();
146360
146803
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
146361
146804
  var HubForwarderDestination = class {
@@ -146489,7 +146932,7 @@ var require_liveness_monitor_addon = __commonJS({
146489
146932
  "use strict";
146490
146933
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
146491
146934
  require_chunk_Cek0wNdY();
146492
- var require_dist10 = require_dist_Bn_RNanh();
146935
+ var require_dist10 = require_dist_D9aw_d0G();
146493
146936
  var NO_DEVICES = "liveness:no-devices";
146494
146937
  var ALL_OFFLINE = "liveness:all-devices-offline";
146495
146938
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -146852,11 +147295,11 @@ var require_local_auth_addon = __commonJS({
146852
147295
  [Symbol.toStringTag]: { value: "Module" }
146853
147296
  });
146854
147297
  var require_chunk = require_chunk_Cek0wNdY();
146855
- var require_dist10 = require_dist_Bn_RNanh();
147298
+ var require_dist10 = require_dist_D9aw_d0G();
146856
147299
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
146857
147300
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
146858
147301
  var require_ms$1 = require_ms_LB3giGoU();
146859
- var require_device_ca = require_device_ca_CPTDs_d();
147302
+ var require_device_ca = require_device_ca_B3xUzps7();
146860
147303
  var zod = require_zod();
146861
147304
  var node_crypto = __require("crypto");
146862
147305
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -152443,7 +152886,6 @@ var require_local_auth_addon = __commonJS({
152443
152886
  var USERS_COLLECTION$1 = "users";
152444
152887
  var API_KEYS_COLLECTION = "api_keys";
152445
152888
  var SCOPED_TOKENS_COLLECTION = "scoped_tokens";
152446
- var OAUTH_SESSIONS_COLLECTION = "oauth_sessions";
152447
152889
  var USER_TOTP_COLLECTION = "user_totp";
152448
152890
  var USER_EXTERNAL_IDENTITIES_COLLECTION = "user_external_identities";
152449
152891
  var USERS_COLUMNS = [
@@ -152643,47 +153085,6 @@ var require_local_auth_addon = __commonJS({
152643
153085
  notNull: true
152644
153086
  }
152645
153087
  ];
152646
- var OAUTH_SESSIONS_COLUMNS = [
152647
- {
152648
- name: "id",
152649
- type: "TEXT",
152650
- primaryKey: true,
152651
- notNull: true
152652
- },
152653
- {
152654
- name: "userId",
152655
- type: "TEXT",
152656
- notNull: true
152657
- },
152658
- {
152659
- name: "username",
152660
- type: "TEXT",
152661
- notNull: true
152662
- },
152663
- {
152664
- name: "integrationId",
152665
- type: "TEXT",
152666
- notNull: true
152667
- },
152668
- {
152669
- name: "scopes",
152670
- type: "JSON"
152671
- },
152672
- {
152673
- name: "createdAt",
152674
- type: "INTEGER",
152675
- notNull: true
152676
- },
152677
- {
152678
- name: "lastUsedAt",
152679
- type: "INTEGER",
152680
- notNull: true
152681
- },
152682
- {
152683
- name: "revokedAt",
152684
- type: "INTEGER"
152685
- }
152686
- ];
152687
153088
  async function declareAuthSchema(store, options) {
152688
153089
  const skip = new Set(options?.skipCollections ?? []);
152689
153090
  if (!skip.has("users")) await store.declareCollection.mutate({
@@ -152718,14 +153119,6 @@ var require_local_auth_addon = __commonJS({
152718
153119
  columns: ["userId"]
152719
153120
  }]
152720
153121
  });
152721
- if (!skip.has("oauth_sessions")) await store.declareCollection.mutate({
152722
- collection: OAUTH_SESSIONS_COLLECTION,
152723
- columns: OAUTH_SESSIONS_COLUMNS,
152724
- indexes: [{
152725
- name: "idx_oauth_sessions_user_id",
152726
- columns: ["userId"]
152727
- }]
152728
- });
152729
153122
  if (!skip.has("login_sessions")) await store.declareCollection.mutate({
152730
153123
  collection: LOGIN_SESSIONS_COLLECTION,
152731
153124
  columns: LOGIN_SESSIONS_COLUMNS,
@@ -152926,16 +153319,19 @@ var require_local_auth_addon = __commonJS({
152926
153319
  "oauth-sessions": {
152927
153320
  schema: OauthSessionBodySchema,
152928
153321
  class: "ledger",
152929
- writeTrigger: "OAuth code exchange; refresh touches lastUsedAt",
153322
+ writeTrigger: "OAuth code exchange; refresh touches lastUsedAt; revoke stamps revokedAt",
152930
153323
  device: "none",
152931
153324
  at: "none",
152932
153325
  indexes: [{
152933
153326
  name: "user",
152934
153327
  fields: ["userId"]
153328
+ }, {
153329
+ name: "revoked",
153330
+ fields: ["revokedAt"]
152935
153331
  }],
152936
153332
  retention: {
152937
153333
  owner: "local-auth",
152938
- reason: "daily reap deletes revoked sessions older than 30 days; active rows never expire"
153334
+ reason: "daily reap deletes sessions revoked more than 30 days ago; an active session has no lifetime, so no engine TTL"
152939
153335
  }
152940
153336
  },
152941
153337
  "user-totp": {
@@ -153015,7 +153411,6 @@ var require_local_auth_addon = __commonJS({
153015
153411
  ADMIN_TOKENS_COLLECTION,
153016
153412
  LOGIN_SESSIONS_COLLECTION,
153017
153413
  LOGIN_SESSION_CUTOFFS_COLLECTION,
153018
- OAUTH_SESSIONS_COLLECTION,
153019
153414
  USER_TOTP_COLLECTION,
153020
153415
  USER_EXTERNAL_IDENTITIES_COLLECTION,
153021
153416
  DEVICE_CREDENTIALS_COLLECTION,
@@ -153163,7 +153558,7 @@ var require_local_auth_addon = __commonJS({
153163
153558
  const value = data[key];
153164
153559
  return typeof value === "number" && Number.isFinite(value) ? value : null;
153165
153560
  }
153166
- function parseSession$1(data) {
153561
+ function parseSession(data) {
153167
153562
  const id = str(data, "id");
153168
153563
  const userId = str(data, "userId");
153169
153564
  const createdAt = num(data, "createdAt");
@@ -153226,7 +153621,7 @@ var require_local_auth_addon = __commonJS({
153226
153621
  if (sessionsKind !== null) {
153227
153622
  const rows2 = await (0, import_read_all_rows.readAllRows)(sessionsKind);
153228
153623
  for (const row of rows2) {
153229
- const record = parseSession$1({
153624
+ const record = parseSession({
153230
153625
  id: row.id,
153231
153626
  ...row.data
153232
153627
  });
@@ -153238,7 +153633,7 @@ var require_local_auth_addon = __commonJS({
153238
153633
  }
153239
153634
  const rows = await this.store.query.query({ collection: LOGIN_SESSIONS_COLLECTION });
153240
153635
  for (const row of rows) {
153241
- const record = parseSession$1(row.data);
153636
+ const record = parseSession(row.data);
153242
153637
  if (record !== null) this.remember(record);
153243
153638
  }
153244
153639
  const cutoffs = await this.store.query.query({ collection: LOGIN_SESSION_CUTOFFS_COLLECTION });
@@ -156565,33 +156960,6 @@ var require_local_auth_addon = __commonJS({
156565
156960
  }
156566
156961
  };
156567
156962
  }
156568
- function parseSession(data) {
156569
- const id = data["id"];
156570
- const userId = data["userId"];
156571
- const username = data["username"];
156572
- const integrationId = data["integrationId"];
156573
- const scopes = data["scopes"];
156574
- const createdAt = data["createdAt"];
156575
- const lastUsedAt = data["lastUsedAt"];
156576
- const revokedAt = data["revokedAt"];
156577
- if (typeof id !== "string") throw new Error("oauth_sessions row: missing id");
156578
- if (typeof userId !== "string") throw new Error("oauth_sessions row: missing userId");
156579
- if (typeof username !== "string") throw new Error("oauth_sessions row: missing username");
156580
- if (typeof integrationId !== "string") throw new Error("oauth_sessions row: missing integrationId");
156581
- if (!Array.isArray(scopes)) throw new Error("oauth_sessions row: scopes must be an array");
156582
- if (typeof createdAt !== "number") throw new Error("oauth_sessions row: missing createdAt");
156583
- if (typeof lastUsedAt !== "number") throw new Error("oauth_sessions row: missing lastUsedAt");
156584
- return {
156585
- id,
156586
- userId,
156587
- username,
156588
- integrationId,
156589
- scopes,
156590
- createdAt,
156591
- lastUsedAt,
156592
- revokedAt: typeof revokedAt === "number" ? revokedAt : null
156593
- };
156594
- }
156595
156963
  function sessionToBody(session) {
156596
156964
  return {
156597
156965
  userId: session.userId,
@@ -156604,22 +156972,29 @@ var require_local_auth_addon = __commonJS({
156604
156972
  };
156605
156973
  }
156606
156974
  function rowToSession(id, body) {
156607
- return parseSession({
156975
+ return {
156608
156976
  id,
156609
- ...body
156610
- });
156977
+ userId: body.userId,
156978
+ username: body.username,
156979
+ integrationId: body.integrationId,
156980
+ scopes: body.scopes,
156981
+ createdAt: body.createdAt,
156982
+ lastUsedAt: body.lastUsedAt,
156983
+ revokedAt: typeof body.revokedAt === "number" ? body.revokedAt : null
156984
+ };
156611
156985
  }
156612
156986
  var OauthSessionManager = class {
156613
156987
  kind;
156614
- store;
156615
156988
  constructor(deps) {
156616
- if ("oauthSessionsKind" in deps) {
156617
- this.kind = deps.oauthSessionsKind;
156618
- this.store = deps.legacyStore ?? null;
156619
- } else {
156620
- this.kind = null;
156621
- this.store = deps;
156622
- }
156989
+ this.kind = deps.oauthSessionsKind;
156990
+ }
156991
+ async write(session) {
156992
+ const parsed = localAuthRecordKinds["oauth-sessions"].schema.safeParse(sessionToBody(session));
156993
+ if (!parsed.success) throw new Error(parsed.error.message);
156994
+ await this.kind.put({
156995
+ id: session.id,
156996
+ data: parsed.data
156997
+ });
156623
156998
  }
156624
156999
  async create(input) {
156625
157000
  const now = Date.now();
@@ -156633,117 +157008,53 @@ var require_local_auth_addon = __commonJS({
156633
157008
  lastUsedAt: now,
156634
157009
  revokedAt: null
156635
157010
  };
156636
- const kind = this.kind;
156637
- if (kind !== null) {
156638
- const parsed = localAuthRecordKinds["oauth-sessions"].schema.safeParse(sessionToBody(session));
156639
- if (!parsed.success) throw new Error(parsed.error.message);
156640
- await kind.put({
156641
- id: session.id,
156642
- data: parsed.data
156643
- });
156644
- return session;
156645
- }
156646
- await this.store.insert.mutate({
156647
- collection: OAUTH_SESSIONS_COLLECTION,
156648
- record: {
156649
- id: session.id,
156650
- data: { ...session }
156651
- }
156652
- });
157011
+ await this.write(session);
156653
157012
  return session;
156654
157013
  }
156655
157014
  async list() {
156656
- const kind = this.kind;
156657
- if (kind !== null) return (await (0, import_read_all_rows.readAllRows)(kind)).map((row) => rowToSession(row.id, row.data));
156658
- return (await this.store.query.query({
156659
- collection: OAUTH_SESSIONS_COLLECTION,
156660
- filter: {}
156661
- })).map((r2) => parseSession(r2.data));
157015
+ return (await (0, import_read_all_rows.readAllRows)(this.kind)).map((row) => rowToSession(row.id, row.data));
156662
157016
  }
156663
157017
  async getById(id) {
156664
- const kind = this.kind;
156665
- if (kind !== null) {
156666
- const row = await kind.get(id);
156667
- return row === null ? null : rowToSession(row.id, row.data);
156668
- }
156669
- const results = await this.store.query.query({
156670
- collection: OAUTH_SESSIONS_COLLECTION,
156671
- filter: { where: { id } }
156672
- });
156673
- if (results.length === 0) return null;
156674
- return parseSession(results[0].data);
157018
+ const row = await this.kind.get(id);
157019
+ return row === null ? null : rowToSession(row.id, row.data);
156675
157020
  }
156676
157021
  async markRevoked(id) {
156677
157022
  const existing = await this.getById(id);
156678
157023
  if (existing === null) return false;
156679
157024
  if (existing.revokedAt !== null) return true;
156680
- const updated = {
157025
+ await this.write({
156681
157026
  ...existing,
156682
157027
  revokedAt: Date.now()
156683
- };
156684
- const kind = this.kind;
156685
- if (kind !== null) {
156686
- const parsed = localAuthRecordKinds["oauth-sessions"].schema.safeParse(sessionToBody(updated));
156687
- if (!parsed.success) throw new Error(parsed.error.message);
156688
- await kind.put({
156689
- id,
156690
- data: parsed.data
156691
- });
156692
- return true;
156693
- }
156694
- await this.store.update.mutate({
156695
- collection: OAUTH_SESSIONS_COLLECTION,
156696
- id,
156697
- data: { ...updated }
156698
157028
  });
156699
157029
  return true;
156700
157030
  }
156701
157031
  async remove(id) {
156702
157032
  if (await this.getById(id) === null) return false;
156703
- const kind = this.kind;
156704
- if (kind !== null) {
156705
- await kind.delete(id);
156706
- return true;
156707
- }
156708
- await this.store.delete.mutate({
156709
- collection: OAUTH_SESSIONS_COLLECTION,
156710
- key: id
156711
- });
157033
+ await this.kind.delete(id);
156712
157034
  return true;
156713
157035
  }
157036
+ /**
157037
+ * Delete the sessions revoked at or before `horizonMs`. An active session
157038
+ * (`revokedAt` null) is never matched: it has no lifetime of its own, which
157039
+ * is why this is the owner's sweep and not an engine TTL.
157040
+ */
156714
157041
  async reapRevoked(horizonMs) {
156715
- const kind = this.kind;
156716
- if (kind !== null) return kind.deleteWhere({ where: { revokedAt: {
157042
+ return this.kind.deleteWhere({ where: { revokedAt: {
156717
157043
  gte: 1,
156718
157044
  lte: horizonMs
156719
157045
  } } });
156720
- const { deleted } = await this.store.deleteWhere.mutate({
156721
- collection: OAUTH_SESSIONS_COLLECTION,
156722
- filter: { whereBetween: { revokedAt: [1, horizonMs] } }
156723
- });
156724
- return deleted;
156725
157046
  }
156726
157047
  async touch(id) {
156727
157048
  const existing = await this.getById(id);
156728
157049
  if (existing === null) return;
156729
- const updated = {
157050
+ const parsed = localAuthRecordKinds["oauth-sessions"].schema.safeParse(sessionToBody({
156730
157051
  ...existing,
156731
157052
  lastUsedAt: Date.now()
156732
- };
156733
- const kind = this.kind;
156734
- if (kind !== null) {
156735
- const parsed = localAuthRecordKinds["oauth-sessions"].schema.safeParse(sessionToBody(updated));
156736
- if (!parsed.success) return;
156737
- await kind.put({
156738
- id,
156739
- data: parsed.data
156740
- });
156741
- return;
156742
- }
156743
- await this.store.update.mutate({
156744
- collection: OAUTH_SESSIONS_COLLECTION,
157053
+ }));
157054
+ if (!parsed.success) return;
157055
+ await this.kind.put({
156745
157056
  id,
156746
- data: { ...updated }
157057
+ data: parsed.data
156747
157058
  });
156748
157059
  }
156749
157060
  };
@@ -156800,10 +157111,7 @@ var require_local_auth_addon = __commonJS({
156800
157111
  apiKeysKind: authStores.apiKeys,
156801
157112
  legacyStore: store
156802
157113
  });
156803
- this.oauthSessionManager = new OauthSessionManager({
156804
- oauthSessionsKind: authStores.oauthSessions,
156805
- legacyStore: store
156806
- });
157114
+ this.oauthSessionManager = new OauthSessionManager({ oauthSessionsKind: authStores.oauthSessions });
156807
157115
  this.totpManager = new TotpManager({
156808
157116
  userTotpKind: authStores.userTotp,
156809
157117
  legacyStore: store
@@ -157523,7 +157831,7 @@ var require_loki_logging = __commonJS({
157523
157831
  [Symbol.toStringTag]: { value: "Module" }
157524
157832
  });
157525
157833
  require_chunk_Cek0wNdY();
157526
- var require_dist10 = require_dist_Bn_RNanh();
157834
+ var require_dist10 = require_dist_D9aw_d0G();
157527
157835
  var require_log_read_filter = require_log_read_filter_Bi066jwU();
157528
157836
  var zod = require_zod();
157529
157837
  function sanitizeLabelName(raw) {
@@ -158484,7 +158792,7 @@ var require_native_metrics_addon = __commonJS({
158484
158792
  [Symbol.toStringTag]: { value: "Module" }
158485
158793
  });
158486
158794
  var require_chunk = require_chunk_Cek0wNdY();
158487
- var require_dist10 = require_dist_Bn_RNanh();
158795
+ var require_dist10 = require_dist_D9aw_d0G();
158488
158796
  var node_fs_promises = __require("fs/promises");
158489
158797
  var node_util = __require("util");
158490
158798
  var node_os = __require("os");
@@ -161051,7 +161359,7 @@ var require_device_history_addon = __commonJS({
161051
161359
  [Symbol.toStringTag]: { value: "Module" }
161052
161360
  });
161053
161361
  require_chunk_Cek0wNdY();
161054
- var require_dist10 = require_dist_Bn_RNanh();
161362
+ var require_dist10 = require_dist_D9aw_d0G();
161055
161363
  var FIVE_MINUTES_MS = 5 * 6e4;
161056
161364
  var HOUR_MS = 60 * 6e4;
161057
161365
  var DAY_MS = 24 * HOUR_MS;
@@ -164097,7 +164405,7 @@ var require_filesystem_storage_addon = __commonJS({
164097
164405
  [Symbol.toStringTag]: { value: "Module" }
164098
164406
  });
164099
164407
  var require_chunk = require_chunk_Cek0wNdY();
164100
- var require_dist10 = require_dist_Bn_RNanh();
164408
+ var require_dist10 = require_dist_D9aw_d0G();
164101
164409
  var node_crypto = __require("crypto");
164102
164410
  var node_fs_promises = __require("fs/promises");
164103
164411
  var node_path = __require("path");
@@ -165207,12 +165515,12 @@ var require_lib = __commonJS({
165207
165515
  }
165208
165516
  });
165209
165517
 
165210
- // ../system/dist/wal-maintenance-CaJjuLHq.js
165211
- var require_wal_maintenance_CaJjuLHq = __commonJS({
165212
- "../system/dist/wal-maintenance-CaJjuLHq.js"(exports) {
165518
+ // ../system/dist/wal-maintenance-jXcOxm2T.js
165519
+ var require_wal_maintenance_jXcOxm2T = __commonJS({
165520
+ "../system/dist/wal-maintenance-jXcOxm2T.js"(exports) {
165213
165521
  "use strict";
165214
165522
  var require_chunk = require_chunk_Cek0wNdY();
165215
- var require_dist10 = require_dist_Bn_RNanh();
165523
+ var require_dist10 = require_dist_D9aw_d0G();
165216
165524
  var require_prefix_range = require_prefix_range_D_KueXbQ();
165217
165525
  var node_crypto = __require("crypto");
165218
165526
  var node_module = __require("module");
@@ -165496,7 +165804,6 @@ var require_wal_maintenance_CaJjuLHq = __commonJS({
165496
165804
  function controlTargetOf(backend, threadId) {
165497
165805
  return {
165498
165806
  hasTable: ({ name }) => backend.hasTable(name),
165499
- dropRetiredTable: ({ name }) => backend.dropRetiredTable(name),
165500
165807
  threadId: () => threadId,
165501
165808
  listPhysicalTables: ({ ownerPrefix }) => backend.listTables(ownerPrefix)
165502
165809
  };
@@ -165588,9 +165895,6 @@ var require_wal_maintenance_CaJjuLHq = __commonJS({
165588
165895
  params
165589
165896
  };
165590
165897
  }
165591
- var RECORDS_TABLE = "records";
165592
- var RECORD_KINDS_TABLE = "_record_kinds";
165593
- var RECORD_SEQUENCES_TABLE = "_record_sequences";
165594
165898
  var RECORDS_SCHEMA_SQL = `
165595
165899
  CREATE TABLE IF NOT EXISTS records (
165596
165900
  rid INTEGER PRIMARY KEY,
@@ -165626,11 +165930,6 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
165626
165930
  next INTEGER NOT NULL
165627
165931
  );
165628
165932
  `;
165629
- var RECORDS_ENGINE_TABLES = [
165630
- RECORDS_TABLE,
165631
- RECORD_KINDS_TABLE,
165632
- RECORD_SEQUENCES_TABLE
165633
- ];
165634
165933
  var INDEX_KIND_DEVICE_AT = "records_kind_device_at";
165635
165934
  var INDEX_KIND_AT = "records_kind_at";
165636
165935
  var FIELD_PATH = /^[A-Za-z_][A-Za-z0-9_]{0,63}(\.[A-Za-z_][A-Za-z0-9_]{0,63}){0,3}$/;
@@ -166634,7 +166933,6 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166634
166933
  ];
166635
166934
  var CONTROL_OPS = [
166636
166935
  "hasTable",
166637
- "dropRetiredTable",
166638
166936
  "threadId",
166639
166937
  "listPhysicalTables"
166640
166938
  ];
@@ -166883,9 +167181,6 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166883
167181
  kind: kind === "table" || kind === "index" ? kind : "unknown"
166884
167182
  };
166885
167183
  }
166886
- function isCountRow(raw) {
166887
- return raw !== null && typeof raw === "object" && typeof Reflect.get(raw, "n") === "number";
166888
- }
166889
167184
  function parseRowData(raw) {
166890
167185
  return require_dist10.asJsonObject(require_dist10.parseJsonUnknown(raw)) ?? {};
166891
167186
  }
@@ -167848,28 +168143,6 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
167848
168143
  return out;
167849
168144
  }
167850
168145
  /**
167851
- * Drop one table nobody owns (D870 migration, one-shot). Refuses a canonical
167852
- * or engine table, one a running addon declared since boot, a table that is
167853
- * not there, and a row count other than the one the caller stated.
167854
- */
167855
- dropTable(name, expectRows) {
167856
- if (name.startsWith("sqlite_") || name === SqliteSettingsBackend2.DECLARATIONS_TABLE) throw new Error(`drop refused: "${name}" is an engine table`);
167857
- if (RECORDS_ENGINE_TABLES.includes(name)) throw new Error(`drop refused: "${name}" is a table of the records engine`);
167858
- if (SqliteSettingsBackend2.CANONICAL_KV_COLLECTIONS.includes(name)) throw new Error(`drop refused: "${name}" is a canonical collection`);
167859
- if (this.declaredThisBoot.has(name)) throw new Error(`drop refused: "${name}" is declared by a running addon`);
167860
- if (!this.hasTable(name)) throw new Error(`drop refused: no table "${name}"`);
167861
- const db = this.getDb();
167862
- const rows = db.prepare(`SELECT COUNT(*) AS c FROM "${name}"`).get()?.c ?? 0;
167863
- if (rows !== expectRows) throw new Error(`drop refused: "${name}" holds ${rows} rows, the caller expected ${expectRows}`);
167864
- db.transaction(() => {
167865
- db.exec(`DROP TABLE "${name}"`);
167866
- this.ensureDeclarationsTable();
167867
- db.prepare(`DELETE FROM "${SqliteSettingsBackend2.DECLARATIONS_TABLE}" WHERE name = ?`).run(name);
167868
- })();
167869
- this.declaredCollections.delete(name);
167870
- return rows;
167871
- }
167872
- /**
167873
168146
  * The tables this file's own `_collection_declarations` names — the
167874
168147
  * placement authority (D851). Read from DISK, not from memory, so a table
167875
168148
  * created and declared by an earlier life of the process still counts.
@@ -168289,31 +168562,6 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
168289
168562
  }
168290
168563
  this.structuredTables.set(table, fingerprint);
168291
168564
  }
168292
- /**
168293
- * Drop a table nothing declares any more, reporting what went with it.
168294
- *
168295
- * The DDL lives here because the engine owns the handle AND the two memos
168296
- * that outlive a table: `structuredTables` (schema fingerprint) and
168297
- * `declaredCollections` (the column set `compileFilter` resolves against).
168298
- * Dropping behind their backs would leave a ghost — a later declaration of
168299
- * the same name would be memoised as "already materialised" against a table
168300
- * that no longer exists.
168301
- *
168302
- * WHICH tables are retired, and the logging, are policy: they live in
168303
- * `retired-collections.ts`. This method knows only how to drop one.
168304
- *
168305
- * Answers `null` when the table is not there — the steady state after the
168306
- * first boot that ran the purge, and the case on a fresh install.
168307
- */
168308
- dropRetiredTable(table) {
168309
- if (this.getDb().prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`).get(table) === void 0) return null;
168310
- const counted = this.getDb().prepare(`SELECT COUNT(*) AS n FROM "${table}"`).get();
168311
- const rows = isCountRow(counted) ? counted.n : 0;
168312
- this.getDb().exec(`DROP TABLE "${table}"`);
168313
- this.structuredTables.delete(table);
168314
- this.declaredCollections.delete(table);
168315
- return { rows };
168316
- }
168317
168565
  /** Returns SQLite's `lastInsertRowid` — the only place an auto-assigned key
168318
168566
  * is knowable (D473). */
168319
168567
  async tableInsert(table, row) {
@@ -169389,9 +169637,9 @@ var require_sqlite_settings_addon = __commonJS({
169389
169637
  [Symbol.toStringTag]: { value: "Module" }
169390
169638
  });
169391
169639
  var require_chunk = require_chunk_Cek0wNdY();
169392
- var require_dist10 = require_dist_Bn_RNanh();
169393
- var require_retired_settings_keys = require_retired_settings_keys_D_VwZiDt();
169394
- var require_wal_maintenance = require_wal_maintenance_CaJjuLHq();
169640
+ var require_dist10 = require_dist_D9aw_d0G();
169641
+ var require_retired_settings_keys = require_retired_settings_keys_CGUqX_Oz();
169642
+ var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
169395
169643
  var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
169396
169644
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
169397
169645
  var node_fs_promises = __require("fs/promises");
@@ -170277,9 +170525,6 @@ var require_sqlite_settings_addon = __commonJS({
170277
170525
  listPhysicalTables(ownerPrefix) {
170278
170526
  return Promise.resolve(require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "listPhysicalTables", { ownerPrefix }));
170279
170527
  }
170280
- async dropRetiredTable(name) {
170281
- return require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "dropRetiredTable", { name });
170282
- }
170283
170528
  async servingThreadId() {
170284
170529
  return 0;
170285
170530
  }
@@ -170333,9 +170578,6 @@ var require_sqlite_settings_addon = __commonJS({
170333
170578
  listPhysicalTables(ownerPrefix) {
170334
170579
  return this.client.control("listPhysicalTables", { ownerPrefix });
170335
170580
  }
170336
- dropRetiredTable(name) {
170337
- return this.client.control("dropRetiredTable", { name });
170338
- }
170339
170581
  servingThreadId() {
170340
170582
  return this.client.control("threadId", {});
170341
170583
  }
@@ -170808,13 +171050,11 @@ var require_sqlite_settings_addon = __commonJS({
170808
171050
  var StorageAdminProvider = class {
170809
171051
  backend;
170810
171052
  logger;
170811
- installedOwners;
170812
171053
  records;
170813
171054
  peerFiles;
170814
- constructor(backend, logger, installedOwners, records, peerFiles = async () => []) {
171055
+ constructor(backend, logger, records, peerFiles = async () => []) {
170815
171056
  this.backend = backend;
170816
171057
  this.logger = logger;
170817
- this.installedOwners = installedOwners;
170818
171058
  this.records = records;
170819
171059
  this.peerFiles = peerFiles;
170820
171060
  }
@@ -170824,19 +171064,6 @@ var require_sqlite_settings_addon = __commonJS({
170824
171064
  readRecords(input) {
170825
171065
  return this.records.readRecords(input);
170826
171066
  }
170827
- /** May this table be dropped AT ALL? Throws with the reason when not. */
170828
- async assertDroppable(collection) {
170829
- const colon = collection.indexOf(":");
170830
- const base = colon > 0 ? collection.slice(colon + 1) : "";
170831
- if (colon > 0 && require_dist10.STORAGE_ADMIN_SCOPED_BASES.includes(base)) return;
170832
- if (require_dist10.STORAGE_ADMIN_MOVED_COLLECTIONS.includes(collection)) return;
170833
- if (colon <= 0) throw new Error(`drop refused: "${collection}" is not a scoped table`);
170834
- const installed = await this.installedOwners().catch((err) => {
170835
- throw new Error(`drop refused: the installed addons could not be read (${err instanceof Error ? err.message : String(err)})`);
170836
- });
170837
- const owner = collection.slice(0, colon);
170838
- if (installed.has(owner)) throw new Error(`drop refused: "${collection}" belongs to the installed addon "${owner}"`);
170839
- }
170840
171067
  async listTables(input) {
170841
171068
  const tables = [...this.backend.listTables(input.ownerPrefix)];
170842
171069
  for (const file of await this.peerFiles()) tables.push(...await file.listPhysicalTables(input.ownerPrefix));
@@ -170847,98 +171074,7 @@ var require_sqlite_settings_addon = __commonJS({
170847
171074
  } });
170848
171075
  return { tables };
170849
171076
  }
170850
- async dropCollection(input) {
170851
- try {
170852
- await this.assertDroppable(input.collection);
170853
- const rows = this.backend.dropTable(input.collection, input.expectRows);
170854
- this.logger.warn("storage-admin: DROPPED a table", { meta: {
170855
- collection: input.collection,
170856
- rows
170857
- } });
170858
- return {
170859
- dropped: true,
170860
- rows
170861
- };
170862
- } catch (err) {
170863
- this.logger.warn("storage-admin: drop refused", { meta: {
170864
- collection: input.collection,
170865
- expectRows: input.expectRows,
170866
- error: err instanceof Error ? err.message : String(err)
170867
- } });
170868
- throw err;
170869
- }
170870
- }
170871
171077
  };
170872
- var RETIRED_COLLECTIONS = [
170873
- {
170874
- collection: "devices",
170875
- owner: "integration-registry",
170876
- reason: "the device half of the integration-registry is deleted; the fleet is `device-manager:devices` and always was (0 rows here against 974 live devices)"
170877
- },
170878
- {
170879
- collection: "device_settings_kv",
170880
- owner: "integration-registry",
170881
- reason: "per-device settings of a device table that never had a row; the live per-camera store is the device-manager row plus `addon-device-settings`"
170882
- },
170883
- {
170884
- collection: "pipeline-analytics:track-groups",
170885
- owner: "pipeline-analytics",
170886
- reason: "the co-moving group entity is deleted (operator decision 2026-09-01, after the 2026-08-24 kill switch); nothing declares, writes or reads it"
170887
- },
170888
- {
170889
- collection: "pipeline-analytics:track-group-members",
170890
- owner: "pipeline-analytics",
170891
- reason: "membership rows of the deleted group entity; the track cascade that used to carry them away no longer has a group leg"
170892
- },
170893
- {
170894
- collection: "pipeline-analytics:summaries",
170895
- owner: "pipeline-analytics",
170896
- reason: "the session summary (proximity track grouping, D489/D490) is deleted (operator decision 2026-09-29, D680, after the 2026-09-16 switch-off); nothing declares, writes or reads it"
170897
- },
170898
- {
170899
- collection: "pipeline-analytics:summary-members",
170900
- owner: "pipeline-analytics",
170901
- reason: "membership rows of the deleted session summary; the track cascade no longer has a summary leg (D680)"
170902
- }
170903
- ];
170904
- function retiredCollectionStoreOfFile(file) {
170905
- return { async drop(collection) {
170906
- return file.dropRetiredTable(collection);
170907
- } };
170908
- }
170909
- async function purgeRetiredCollections(store, logger, specs = RETIRED_COLLECTIONS) {
170910
- const results = [];
170911
- for (const spec of specs) {
170912
- let dropped;
170913
- try {
170914
- dropped = await store.drop(spec.collection);
170915
- } catch (err) {
170916
- logger.warn("retired collection \u2014 drop failed, table left in place", { meta: {
170917
- addon: spec.owner,
170918
- collection: spec.collection,
170919
- error: err instanceof Error ? err.message : String(err)
170920
- } });
170921
- continue;
170922
- }
170923
- if (dropped === null) continue;
170924
- const result = {
170925
- collection: spec.collection,
170926
- owner: spec.owner,
170927
- rows: dropped.rows
170928
- };
170929
- results.push(result);
170930
- const line = "dropped a retired collection";
170931
- if (dropped.rows > 0) logger.warn(`${line} \u2014 it still held rows`, { meta: {
170932
- ...result,
170933
- reason: spec.reason
170934
- } });
170935
- else logger.info(line, { meta: {
170936
- ...result,
170937
- reason: spec.reason
170938
- } });
170939
- }
170940
- return results;
170941
- }
170942
171078
  var DATABASE_FILE_NAMES = {
170943
171079
  settings: "camstack.db",
170944
171080
  events: "events.db",
@@ -171028,14 +171164,13 @@ var require_sqlite_settings_addon = __commonJS({
171028
171164
  },
171029
171165
  {
171030
171166
  capability: require_dist10.storageAdminCapability,
171031
- provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), async () => new Set((await this.ctx.api.addons.list.query()).map((addon) => addon.manifest.id)), records, async () => router.openFiles().filter((file) => file.databaseId !== "settings"))
171167
+ provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), records, async () => router.openFiles().filter((file) => file.databaseId !== "settings"))
171032
171168
  }
171033
171169
  ];
171034
171170
  }
171035
171171
  /**
171036
171172
  * Housekeeping that must happen BEFORE anything can read a file: the
171037
- * retired-key purge (settings only) and the retired-table purge (every
171038
- * open file).
171173
+ * retired-key purge (settings file only).
171039
171174
  */
171040
171175
  async purgeBeforeServing(file) {
171041
171176
  if (file instanceof InlineOwnedFile && file.databaseId === "settings") try {
@@ -171043,7 +171178,6 @@ var require_sqlite_settings_addon = __commonJS({
171043
171178
  } catch (err) {
171044
171179
  this.ctx.logger.warn("Retired-key purge failed", { meta: { error: require_dist10.errMsg(err) } });
171045
171180
  }
171046
- await purgeRetiredCollections(retiredCollectionStoreOfFile(file), this.ctx.logger.child("RetiredCollections").withTags({ database: file.databaseId }));
171047
171181
  }
171048
171182
  /**
171049
171183
  * The engine's TTL sweep (D881): every 10 minutes, off the boot path (the
@@ -171118,7 +171252,7 @@ var require_sqlite_storage = __commonJS({
171118
171252
  });
171119
171253
  require_chunk_Cek0wNdY();
171120
171254
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
171121
- var require_wal_maintenance = require_wal_maintenance_CaJjuLHq();
171255
+ var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
171122
171256
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
171123
171257
  var ConfigStore = class {
171124
171258
  db;
@@ -171202,7 +171336,7 @@ var require_storage_orchestrator_addon = __commonJS({
171202
171336
  [Symbol.toStringTag]: { value: "Module" }
171203
171337
  });
171204
171338
  var require_chunk = require_chunk_Cek0wNdY();
171205
- var require_dist10 = require_dist_Bn_RNanh();
171339
+ var require_dist10 = require_dist_D9aw_d0G();
171206
171340
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
171207
171341
  var zod = require_zod();
171208
171342
  var node_crypto = __require("crypto");
@@ -175789,12 +175923,12 @@ var require_storage_orchestrator = __commonJS({
175789
175923
  }
175790
175924
  });
175791
175925
 
175792
- // ../system/dist/agent-https-Dnr_nIVx.js
175793
- var require_agent_https_Dnr_nIVx = __commonJS({
175794
- "../system/dist/agent-https-Dnr_nIVx.js"(exports) {
175926
+ // ../system/dist/agent-https-DhFIbEwN.js
175927
+ var require_agent_https_DhFIbEwN = __commonJS({
175928
+ "../system/dist/agent-https-DhFIbEwN.js"(exports) {
175795
175929
  "use strict";
175796
175930
  var require_chunk = require_chunk_Cek0wNdY();
175797
- var require_dist10 = require_dist_Bn_RNanh();
175931
+ var require_dist10 = require_dist_D9aw_d0G();
175798
175932
  var require_x509_es = require_x509_es_C4cOo48M();
175799
175933
  var zod = require_zod();
175800
175934
  var node_crypto = __require("crypto");
@@ -176852,11 +176986,11 @@ var require_agent_https_Dnr_nIVx = __commonJS({
176852
176986
  }
176853
176987
  });
176854
176988
 
176855
- // ../system/dist/constants-6OeJiZgi.js
176856
- var require_constants_6OeJiZgi = __commonJS({
176857
- "../system/dist/constants-6OeJiZgi.js"(exports) {
176989
+ // ../system/dist/constants-5mrGZxwS.js
176990
+ var require_constants_5mrGZxwS = __commonJS({
176991
+ "../system/dist/constants-5mrGZxwS.js"(exports) {
176858
176992
  "use strict";
176859
- var MESH_CA_KEY_REF = require_dist_Bn_RNanh().buildSecretRef({
176993
+ var MESH_CA_KEY_REF = require_dist_D9aw_d0G().buildSecretRef({
176860
176994
  owner: "system",
176861
176995
  scope: { kind: "global" },
176862
176996
  fieldPath: "meshCaKey"
@@ -193953,11 +194087,11 @@ var require_system_config_addon = __commonJS({
193953
194087
  [Symbol.toStringTag]: { value: "Module" }
193954
194088
  });
193955
194089
  var require_chunk = require_chunk_Cek0wNdY();
193956
- var require_dist10 = require_dist_Bn_RNanh();
194090
+ var require_dist10 = require_dist_D9aw_d0G();
193957
194091
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
193958
194092
  var require_x509_es = require_x509_es_C4cOo48M();
193959
- var require_agent_https = require_agent_https_Dnr_nIVx();
193960
- var require_constants$8 = require_constants_6OeJiZgi();
194093
+ var require_agent_https = require_agent_https_DhFIbEwN();
194094
+ var require_constants$8 = require_constants_5mrGZxwS();
193961
194095
  var require_src$1 = require_src_CnAqG6EF();
193962
194096
  var zod = require_zod();
193963
194097
  var node_crypto = __require("crypto");
@@ -275009,7 +275143,7 @@ var require_winston_logging = __commonJS({
275009
275143
  [Symbol.toStringTag]: { value: "Module" }
275010
275144
  });
275011
275145
  var require_chunk = require_chunk_Cek0wNdY();
275012
- var require_dist10 = require_dist_Bn_RNanh();
275146
+ var require_dist10 = require_dist_D9aw_d0G();
275013
275147
  var require_formatter = require_formatter_DqAKDlvN();
275014
275148
  var require_log_file_read_protocol = require_log_file_read_protocol_D0WcLbIV();
275015
275149
  var node_path = __require("path");
@@ -282812,14 +282946,14 @@ var require_lib_8oZrELLm = __commonJS({
282812
282946
  }
282813
282947
  });
282814
282948
 
282815
- // ../system/dist/hub-mdns-ciao-CTBTlia4.js
282816
- var require_hub_mdns_ciao_CTBTlia4 = __commonJS({
282817
- "../system/dist/hub-mdns-ciao-CTBTlia4.js"(exports) {
282949
+ // ../system/dist/hub-mdns-ciao-CFlhVKK6.js
282950
+ var require_hub_mdns_ciao_CFlhVKK6 = __commonJS({
282951
+ "../system/dist/hub-mdns-ciao-CFlhVKK6.js"(exports) {
282818
282952
  "use strict";
282819
282953
  var require_chunk = require_chunk_Cek0wNdY();
282820
- var require_dist10 = require_dist_Bn_RNanh();
282954
+ var require_dist10 = require_dist_D9aw_d0G();
282821
282955
  var require_x509_es = require_x509_es_C4cOo48M();
282822
- var require_agent_https = require_agent_https_Dnr_nIVx();
282956
+ var require_agent_https = require_agent_https_DhFIbEwN();
282823
282957
  var node_crypto = __require("crypto");
282824
282958
  var _camstack_types_node = require_node();
282825
282959
  var node_fs_promises = __require("fs/promises");
@@ -283831,12 +283965,12 @@ var require_platform_key_source_Di7HrlGR = __commonJS({
283831
283965
  }
283832
283966
  });
283833
283967
 
283834
- // ../system/dist/restore-archive-DM1OBYq4.js
283835
- var require_restore_archive_DM1OBYq4 = __commonJS({
283836
- "../system/dist/restore-archive-DM1OBYq4.js"(exports) {
283968
+ // ../system/dist/restore-archive-6zkRREHO.js
283969
+ var require_restore_archive_6zkRREHO = __commonJS({
283970
+ "../system/dist/restore-archive-6zkRREHO.js"(exports) {
283837
283971
  "use strict";
283838
283972
  var require_chunk = require_chunk_Cek0wNdY();
283839
- var require_dist10 = require_dist_Bn_RNanh();
283973
+ var require_dist10 = require_dist_D9aw_d0G();
283840
283974
  var zod = require_zod();
283841
283975
  var node_crypto = __require("crypto");
283842
283976
  var buffer = __require("buffer");
@@ -295077,9 +295211,9 @@ var require_dist3 = __commonJS({
295077
295211
  "use strict";
295078
295212
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
295079
295213
  var require_chunk = require_chunk_Cek0wNdY();
295080
- var require_dist10 = require_dist_Bn_RNanh();
295214
+ var require_dist10 = require_dist_D9aw_d0G();
295081
295215
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
295082
- var require_device_ca = require_device_ca_CPTDs_d();
295216
+ var require_device_ca = require_device_ca_B3xUzps7();
295083
295217
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
295084
295218
  require_alerts();
295085
295219
  var require_builtins_calendars_calendars_addon = require_calendars_addon();
@@ -295088,11 +295222,9 @@ var require_dist3 = __commonJS({
295088
295222
  require_composer();
295089
295223
  var require_formatter = require_formatter_DqAKDlvN();
295090
295224
  var require_builtins_console_logging_index = require_console_logging();
295091
- var require_prefix_range = require_prefix_range_D_KueXbQ();
295092
295225
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
295093
295226
  var require_builtins_core_blocks_core_blocks_addon = require_core_blocks_addon();
295094
295227
  require_core_blocks();
295095
- var require_retired_settings_keys = require_retired_settings_keys_D_VwZiDt();
295096
295228
  var require_builtins_device_manager_device_manager_addon = require_device_manager_addon();
295097
295229
  require_device_manager();
295098
295230
  var require_builtins_hub_forwarder_index = require_hub_forwarder();
@@ -295105,21 +295237,21 @@ var require_dist3 = __commonJS({
295105
295237
  var require_builtins_native_metrics_native_metrics_addon = require_native_metrics_addon();
295106
295238
  var require_builtins_device_history_device_history_addon = require_device_history_addon();
295107
295239
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
295108
- var require_wal_maintenance = require_wal_maintenance_CaJjuLHq();
295240
+ var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
295109
295241
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
295110
295242
  var require_builtins_sqlite_storage_index = require_sqlite_storage();
295111
295243
  var require_builtins_storage_orchestrator_storage_orchestrator_addon = require_storage_orchestrator_addon();
295112
295244
  require_storage_orchestrator();
295113
- var require_agent_https = require_agent_https_Dnr_nIVx();
295114
- var require_constants15 = require_constants_6OeJiZgi();
295245
+ var require_agent_https = require_agent_https_DhFIbEwN();
295246
+ var require_constants15 = require_constants_5mrGZxwS();
295115
295247
  var require_builtins_system_config_system_config_addon = require_system_config_addon();
295116
295248
  require_system_config();
295117
295249
  var require_builtins_winston_logging_index = require_winston_logging();
295118
295250
  var require_custom_action_registry = require_custom_action_registry_MRyes5j0();
295119
- var require_hub_mdns_ciao = require_hub_mdns_ciao_CTBTlia4();
295251
+ var require_hub_mdns_ciao = require_hub_mdns_ciao_CFlhVKK6();
295120
295252
  var require_platform_key_source = require_platform_key_source_Di7HrlGR();
295121
295253
  var require_resource_monitor = require_resource_monitor_mio9dSCT();
295122
- var require_restore_archive = require_restore_archive_DM1OBYq4();
295254
+ var require_restore_archive = require_restore_archive_6zkRREHO();
295123
295255
  var require_coral_accelerators = require_coral_accelerators_oUXmmbc2();
295124
295256
  var zod = require_zod();
295125
295257
  var node_crypto = __require("crypto");
@@ -295909,22 +296041,22 @@ var require_dist3 = __commonJS({
295909
296041
  const queuedTop = window2.queued.top.map((p) => `${p.peerId}:${kb$1(p.bytes)}`).join(",");
295910
296042
  return ` socketPeers=${window2.peersMeasured}/${window2.peersConnected} socketTx=${formatDirection(window2.tx)} socketRx=${formatDirection(window2.rx)}` + (top.length === 0 ? "" : ` socketTop=${top}`) + (topBytes.length === 0 ? "" : ` socketTopBytes=${topBytes}`) + ` socketQueued=${kb$1(window2.queued.totalBytes)}kB` + (window2.queued.unmeasured === 0 ? "" : ` socketQueuedUnmeasured=${window2.queued.unmeasured}`) + (queuedTop.length === 0 ? "" : ` socketQueuedTop=${queuedTop}`) + (window2.forward === void 0 ? "" : ` socketFwd=${window2.forward.raw}/${window2.forward.decoded}`) + (window2.actions === void 0 ? "" : ` socketActions=${kb$1(window2.actions.labelledBytes)}/${kb$1(window2.actions.totalBytes)}kB` + (window2.actions.top.length === 0 ? "" : ` socketTopActions=${window2.actions.top.map(formatAction).join(",")}`));
295911
296043
  }
295912
- function isRecord$7(value) {
296044
+ function isRecord$6(value) {
295913
296045
  return typeof value === "object" && value !== null;
295914
296046
  }
295915
296047
  function writerSocketsOf(broker) {
295916
- if (!isRecord$7(broker)) return void 0;
296048
+ if (!isRecord$6(broker)) return void 0;
295917
296049
  const transit = broker["transit"];
295918
- if (!isRecord$7(transit)) return void 0;
296050
+ if (!isRecord$6(transit)) return void 0;
295919
296051
  const transporter = transit["tx"];
295920
- if (!isRecord$7(transporter)) return void 0;
296052
+ if (!isRecord$6(transporter)) return void 0;
295921
296053
  const writer = transporter["writer"];
295922
- if (!isRecord$7(writer)) return void 0;
296054
+ if (!isRecord$6(writer)) return void 0;
295923
296055
  const sockets = writer["sockets"];
295924
296056
  return sockets instanceof Map ? sockets : void 0;
295925
296057
  }
295926
296058
  function readSocket(nodeId, socket) {
295927
- if (typeof nodeId !== "string" || !isRecord$7(socket)) return void 0;
296059
+ if (typeof nodeId !== "string" || !isRecord$6(socket)) return void 0;
295928
296060
  const queuedBytes = socket["writableLength"];
295929
296061
  const bytesWritten = socket["bytesWritten"];
295930
296062
  if (typeof queuedBytes !== "number" || typeof bytesWritten !== "number") return void 0;
@@ -299530,7 +299662,6 @@ var require_dist3 = __commonJS({
299530
299662
  };
299531
299663
  }
299532
299664
  };
299533
- var CLUSTER_NODE_HISTORY_COLLECTION = "cluster-node-history";
299534
299665
  var NodePackageEntrySchema = zod.z.object({
299535
299666
  name: zod.z.string(),
299536
299667
  version: zod.z.string().nullable()
@@ -299823,27 +299954,27 @@ var require_dist3 = __commonJS({
299823
299954
  throw new Error(`no system npm on PATH and the npm bootstrap failed \u2014 cannot install addon dependencies on this node: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
299824
299955
  }
299825
299956
  }
299826
- function isRecord$6(value) {
299957
+ function isRecord$5(value) {
299827
299958
  return typeof value === "object" && value !== null && !Array.isArray(value);
299828
299959
  }
299829
299960
  function isAddonConstructor(fn) {
299830
299961
  if (typeof fn !== "function") return false;
299831
299962
  const proto = fn.prototype;
299832
- if (!isRecord$6(proto)) return false;
299963
+ if (!isRecord$5(proto)) return false;
299833
299964
  return typeof proto["initialize"] === "function";
299834
299965
  }
299835
299966
  function resolveAddonClass(mod) {
299836
299967
  let candidate = mod["default"];
299837
- if (isRecord$6(candidate) && "default" in candidate) candidate = candidate["default"];
299968
+ if (isRecord$5(candidate) && "default" in candidate) candidate = candidate["default"];
299838
299969
  if (isAddonConstructor(candidate)) return candidate;
299839
- if (isRecord$6(candidate)) {
299970
+ if (isRecord$5(candidate)) {
299840
299971
  const fn = Object.values(candidate).find(isAddonConstructor);
299841
299972
  if (fn) return fn;
299842
299973
  }
299843
299974
  const namedAddon = Object.values(mod).find(isAddonConstructor);
299844
299975
  if (namedAddon) return namedAddon;
299845
299976
  }
299846
- function isRecord$5(value) {
299977
+ function isRecord$4(value) {
299847
299978
  return typeof value === "object" && value !== null && !Array.isArray(value);
299848
299979
  }
299849
299980
  var PACKAGE_JSON_LOOKUP_DEPTH = 4;
@@ -299883,12 +300014,12 @@ var require_dist3 = __commonJS({
299883
300014
  return import(`${(0, node_url.pathToFileURL)(entryPath).href}?v=${encodeURIComponent(bust)}`);
299884
300015
  }
299885
300016
  function isAddonPackageManifest(value) {
299886
- if (!isRecord$5(value)) return false;
300017
+ if (!isRecord$4(value)) return false;
299887
300018
  if (!Array.isArray(value.addons)) return false;
299888
- return value.addons.every((a) => isRecord$5(a) && typeof a.id === "string");
300019
+ return value.addons.every((a) => isRecord$4(a) && typeof a.id === "string");
299889
300020
  }
299890
300021
  function toAddonPackageManifest(value) {
299891
- if (!isRecord$5(value)) return void 0;
300022
+ if (!isRecord$4(value)) return void 0;
299892
300023
  if (!isAddonPackageManifest(value)) return void 0;
299893
300024
  return value;
299894
300025
  }
@@ -300045,7 +300176,7 @@ var require_dist3 = __commonJS({
300045
300176
  }
300046
300177
  if (!node_fs.existsSync(entryPath)) throw new Error(`Entry not found: ${entryPath}`);
300047
300178
  const modUnknown = await importAddonModuleFresh(entryPath);
300048
- const mod = isRecord$5(modUnknown) ? modUnknown : {};
300179
+ const mod = isRecord$4(modUnknown) ? modUnknown : {};
300049
300180
  const AddonClass = resolveAddonClass(mod);
300050
300181
  if (!AddonClass) throw new Error(`No addon class in ${entryPath}`);
300051
300182
  this.addons.set(declaration.id, {
@@ -300061,7 +300192,7 @@ var require_dist3 = __commonJS({
300061
300192
  /** Load addon from a direct path (for development/testing) */
300062
300193
  async loadFromPath(addonId, modulePath, packageName, declaration, packageVersion = "0.0.0") {
300063
300194
  const modUnknown = await importAddonModuleFresh(modulePath);
300064
- const mod = isRecord$5(modUnknown) ? modUnknown : {};
300195
+ const mod = isRecord$4(modUnknown) ? modUnknown : {};
300065
300196
  const AddonClass = resolveAddonClass(mod);
300066
300197
  if (!AddonClass) throw new Error(`Module ${modulePath} has no default export`);
300067
300198
  this.addons.set(addonId, {
@@ -304332,11 +304463,11 @@ var require_dist3 = __commonJS({
304332
304463
  await steps.bootInProcessConsumers();
304333
304464
  await steps.spawnIsolatedConsumers();
304334
304465
  }
304335
- function isRecord$4(value) {
304466
+ function isRecord$3(value) {
304336
304467
  return typeof value === "object" && value !== null && !Array.isArray(value);
304337
304468
  }
304338
304469
  function asBlob(value) {
304339
- return isRecord$4(value) ? value : {};
304470
+ return isRecord$3(value) ? value : {};
304340
304471
  }
304341
304472
  async function loadSystemSettingsPrefix(door, prefix, mayRead = () => true) {
304342
304473
  const listed = await require_prefix_walk.loadPrefixed(door, "system-settings", prefix, () => null);
@@ -306884,7 +307015,7 @@ var require_dist3 = __commonJS({
306884
307015
  })))(), 1);
306885
307016
  var { Type, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA, load: load2, loadAll, dump, YAMLException, types, safeLoad, safeLoadAll, safeDump } = import_js_yaml.default;
306886
307017
  import_js_yaml.default;
306887
- function isRecord$3(value) {
307018
+ function isRecord$2(value) {
306888
307019
  return typeof value === "object" && value !== null && !Array.isArray(value);
306889
307020
  }
306890
307021
  var BOOTSTRAP_SECTIONS = /* @__PURE__ */ new Set([
@@ -306961,7 +307092,7 @@ var require_dist3 = __commonJS({
306961
307092
  [head]: value
306962
307093
  };
306963
307094
  const existing = obj[head];
306964
- const child = isRecord$3(existing) ? existing : {};
307095
+ const child = isRecord$2(existing) ? existing : {};
306965
307096
  return {
306966
307097
  ...obj,
306967
307098
  [head]: setNested(child, rest.join("."), value)
@@ -307170,7 +307301,7 @@ var require_dist3 = __commonJS({
307170
307301
  }
307171
307302
  }
307172
307303
  };
307173
- function isRecord$2(value) {
307304
+ function isRecord$1(value) {
307174
307305
  return typeof value === "object" && value !== null && !Array.isArray(value);
307175
307306
  }
307176
307307
  function errorText(err) {
@@ -307535,7 +307666,7 @@ var require_dist3 = __commonJS({
307535
307666
  const keys = configPath.split(".");
307536
307667
  let current = this.bootstrapConfig;
307537
307668
  for (const key of keys) {
307538
- if (!isRecord$2(current)) return void 0;
307669
+ if (!isRecord$1(current)) return void 0;
307539
307670
  current = current[key];
307540
307671
  }
307541
307672
  return current;
@@ -308304,7 +308435,7 @@ var require_dist3 = __commonJS({
308304
308435
  this.name = "RuntimeStateLoadError";
308305
308436
  }
308306
308437
  };
308307
- function isRecord$1(value) {
308438
+ function isRecord(value) {
308308
308439
  return typeof value === "object" && value !== null && !Array.isArray(value);
308309
308440
  }
308310
308441
  function errorMessage(err) {
@@ -308330,7 +308461,7 @@ var require_dist3 = __commonJS({
308330
308461
  } catch (err) {
308331
308462
  return refuse2(errorMessage(err), err);
308332
308463
  }
308333
- if (!isRecord$1(answer)) return refuse2(`answered ${answer === null ? "null" : typeof answer}`);
308464
+ if (!isRecord(answer)) return refuse2(`answered ${answer === null ? "null" : typeof answer}`);
308334
308465
  return answer;
308335
308466
  }
308336
308467
  var ACCESSORY_SPAWN_CONCURRENCY = 12;
@@ -314243,8 +314374,7 @@ var require_dist3 = __commonJS({
314243
314374
  }
314244
314375
  };
314245
314376
  }
314246
- function createRunnerAddonSettings(client, addonId, before = async () => {
314247
- }) {
314377
+ function createRunnerAddonSettings(client, addonId) {
314248
314378
  if (client === void 0) {
314249
314379
  const refuse2 = async () => {
314250
314380
  throw new Error(`settings of "${addonId}": settings store not wired`);
@@ -314266,22 +314396,10 @@ var require_dist3 = __commonJS({
314266
314396
  };
314267
314397
  }
314268
314398
  const door = {
314269
- query: async (input) => {
314270
- await before();
314271
- return client.query.query(input);
314272
- },
314273
- get: async (input) => {
314274
- await before();
314275
- return client.get.query(input);
314276
- },
314277
- set: async (input) => {
314278
- await before();
314279
- return client.set.mutate(input);
314280
- },
314281
- transact: async (input) => {
314282
- await before();
314283
- return client.transact.mutate(input);
314284
- }
314399
+ query: (input) => client.query.query(input),
314400
+ get: (input) => client.get.query(input),
314401
+ set: (input) => client.set.mutate(input),
314402
+ transact: (input) => client.transact.mutate(input)
314285
314403
  };
314286
314404
  const store = require_builtins_core_blocks_core_blocks_addon.createAddonSettingsStore(door, addonId);
314287
314405
  const sections = createSectionsStore(door);
@@ -314327,141 +314445,14 @@ var require_dist3 = __commonJS({
314327
314445
  setSection: (section, patch) => sections.write(section, patch)
314328
314446
  };
314329
314447
  }
314330
- var AddonRefusedError = class extends Error {
314331
- /** Stable, greppable cause, e.g. `unmigrated-settings`. */
314332
- code;
314333
- /** What the operator does about it. */
314334
- remedy;
314335
- constructor(code, message, remedy, options) {
314336
- super(message, options);
314337
- this.name = "AddonRefusedError";
314338
- this.code = code;
314339
- this.remedy = remedy;
314340
- }
314341
- };
314342
- function findAddonRefusal(err) {
314343
- const seen = /* @__PURE__ */ new Set();
314344
- let current = err;
314345
- while (current !== null && current !== void 0 && !seen.has(current)) {
314346
- if (current instanceof AddonRefusedError) return current;
314347
- seen.add(current);
314348
- current = current instanceof Error ? current.cause : void 0;
314349
- }
314350
- return null;
314351
- }
314352
- var OWN_RETIRED_ROOT_KEYS = /* @__PURE__ */ new Set([
314353
- "recordingConfigs",
314354
- "recordingExports",
314355
- "recordingOpsLog",
314356
- "probeSnapshots",
314357
- "rtspTokens",
314358
- "profileMap"
314359
- ]);
314360
- function isRetiredRootKey(addonId, key) {
314361
- if (OWN_RETIRED_ROOT_KEYS.has(key)) return true;
314362
- return require_retired_settings_keys.RETIRED_SETTINGS_KEYS.some((spec) => spec.namespace === addonId && (spec.keys.includes(key) || spec.perNodeKeys.some((k) => key === k || key.startsWith(`${k}@`))));
314363
- }
314364
- var UNMIGRATED_SETTINGS_CODE = "unmigrated-settings";
314365
- var UNMIGRATED_SETTINGS_REMEDY = "Run scripts/hub/migrate-device-store.ts --copy --apply (D870), then restart the addon.";
314366
- var UnmigratedSettingsError = class extends AddonRefusedError {
314367
- constructor(addonId, what) {
314368
- super(UNMIGRATED_SETTINGS_CODE, `addon "${addonId}" refuses to start: ${what} - the settings it had are still in the per-addon tables and the standard store holds none. Run scripts/hub/migrate-device-store.ts --copy --apply (D870) before starting it.`, UNMIGRATED_SETTINGS_REMEDY);
314369
- this.name = "UnmigratedSettingsError";
314370
- }
314371
- };
314372
- async function countOf(client, input) {
314373
- const n = await client.count.query(input);
314374
- if (typeof n !== "number") throw new Error("settings store answered a non-number to a count");
314375
- return n;
314376
- }
314377
- var LEGACY_PAGE = 500;
314378
- var LEGACY_PAGE_BUDGET = 200;
314379
- var ID_TAIL = "\x7F";
314380
- function isRecord(value) {
314381
- return typeof value === "object" && value !== null && !Array.isArray(value);
314382
- }
314383
- async function hasMigratableDeviceRow(client, addonId) {
314384
- let cursor = "";
314385
- for (let page = 0; page < LEGACY_PAGE_BUDGET; page++) {
314386
- const rows = await client.query.query({
314387
- namespace: addonId,
314388
- collection: "addon-devices",
314389
- filter: {
314390
- whereBetween: { id: [cursor, ID_TAIL] },
314391
- orderBy: {
314392
- field: "id",
314393
- direction: "asc"
314394
- },
314395
- limit: LEGACY_PAGE
314396
- }
314397
- });
314398
- if (!Array.isArray(rows)) throw new Error("settings store answered a non-list to a query");
314399
- let lastId = cursor;
314400
- for (const row of rows) {
314401
- if (!isRecord(row) || typeof row["id"] !== "string") continue;
314402
- lastId = row["id"];
314403
- const id = Number(row["id"]);
314404
- const data = row["data"];
314405
- if (Number.isInteger(id) && id > 0 && isRecord(data) && Object.keys(data).length > 0) return true;
314406
- }
314407
- if (rows.length < LEGACY_PAGE || lastId === cursor) return false;
314408
- cursor = lastId;
314409
- }
314410
- throw new Error(`addon "${addonId}": more legacy blob pages than the guard will read`);
314411
- }
314412
- async function assertLegacyBlobsMigrated(client, addonId, logger) {
314413
- const legacyDevices = await hasMigratableDeviceRow(client, addonId);
314414
- const root = await client.get.query({
314415
- namespace: addonId,
314416
- collection: "addon-settings",
314417
- key: "root"
314418
- });
314419
- const legacySettings = isRecord(root) && Object.keys(root).some((key) => !isRetiredRootKey(addonId, key));
314420
- if (!legacyDevices && !legacySettings) return;
314421
- const rangeOf = (prefix) => {
314422
- const range = require_prefix_range.prefixRange(prefix);
314423
- if (range === null) throw new Error(`no id range for addon "${addonId}"`);
314424
- return { whereBetween: { id: [range.lo, range.hi] } };
314425
- };
314426
- const newDevices = await countOf(client, {
314427
- collection: "addon-device-settings",
314428
- filter: rangeOf(`${addonId}:`)
314429
- });
314430
- const newSettings = await countOf(client, {
314431
- collection: "addon-settings",
314432
- filter: rangeOf(`${addonId}.`)
314433
- });
314434
- const problems = [];
314435
- if (legacyDevices && newDevices === 0) problems.push("per-device blobs");
314436
- if (legacySettings && newSettings === 0) problems.push("an addon settings blob");
314437
- if (problems.length === 0) return;
314438
- const error = new UnmigratedSettingsError(addonId, problems.join(" and "));
314439
- logger.error(error.message, { meta: {
314440
- addonId,
314441
- newDevices,
314442
- newSettings
314443
- } });
314444
- throw error;
314445
- }
314446
- function doorOverClient(client, before = async () => {
314447
- }) {
314448
+ function doorOverClient(client) {
314448
314449
  return {
314449
- query: async (input) => {
314450
- await before();
314451
- return client.query.query(input);
314452
- },
314453
- transact: async (input) => {
314454
- await before();
314455
- return client.transact.mutate(input);
314456
- },
314457
- deleteWhere: async (input) => {
314458
- await before();
314459
- return client.deleteWhere.mutate(input);
314460
- }
314450
+ query: (input) => client.query.query(input),
314451
+ transact: (input) => client.transact.mutate(input),
314452
+ deleteWhere: (input) => client.deleteWhere.mutate(input)
314461
314453
  };
314462
314454
  }
314463
- function createRunnerDeviceSettings(client, addonId, before = async () => {
314464
- }) {
314455
+ function createRunnerDeviceSettings(client, addonId) {
314465
314456
  if (client === void 0) {
314466
314457
  const refuse2 = () => {
314467
314458
  throw new Error(`device settings of "${addonId}": settings store not wired`);
@@ -314474,7 +314465,7 @@ var require_dist3 = __commonJS({
314474
314465
  clearDeviceStore: async () => refuse2()
314475
314466
  };
314476
314467
  }
314477
- const store = require_builtins_device_manager_device_manager_addon.createDeviceSettingsStore(doorOverClient(client, before), addonId);
314468
+ const store = require_builtins_device_manager_device_manager_addon.createDeviceSettingsStore(doorOverClient(client), addonId);
314478
314469
  return {
314479
314470
  readDeviceStore: (deviceId) => require_builtins_device_manager_device_manager_addon.readDeviceOrThrow(store, deviceId),
314480
314471
  readDeviceStoreBatch: (ids) => store.readBatch(ids),
@@ -314676,23 +314667,9 @@ var require_dist3 = __commonJS({
314676
314667
  }
314677
314668
  };
314678
314669
  const deviceSettingsClient = Reflect.get(api, "settingsStore");
314679
- let blobsChecked = null;
314680
- const bootGuard = () => {
314681
- const client = deviceSettingsClient;
314682
- if (client === void 0) return Promise.resolve();
314683
- blobsChecked ??= assertLegacyBlobsMigrated({
314684
- get: { query: (input) => client.get.query(input) },
314685
- query: { query: (input) => client.query.query(input) },
314686
- count: { query: (input) => client.count.query(input) }
314687
- }, addonId, scopedLogger).catch((err) => {
314688
- blobsChecked = null;
314689
- throw err;
314690
- });
314691
- return blobsChecked;
314692
- };
314693
314670
  const settingsView = {
314694
- ...createRunnerAddonSettings(deviceSettingsClient, addonId, bootGuard),
314695
- ...createRunnerDeviceSettings(deviceSettingsClient, addonId, bootGuard),
314671
+ ...createRunnerAddonSettings(deviceSettingsClient, addonId),
314672
+ ...createRunnerDeviceSettings(deviceSettingsClient, addonId),
314696
314673
  async readDeviceRuntimeState(deviceId) {
314697
314674
  return readBlob("device-runtime-state", String(deviceId));
314698
314675
  },
@@ -316780,6 +316757,28 @@ var require_dist3 = __commonJS({
316780
316757
  }
316781
316758
  };
316782
316759
  }
316760
+ var AddonRefusedError = class extends Error {
316761
+ /** Stable, greppable cause, e.g. `unmigrated-settings`. */
316762
+ code;
316763
+ /** What the operator does about it. */
316764
+ remedy;
316765
+ constructor(code, message, remedy, options) {
316766
+ super(message, options);
316767
+ this.name = "AddonRefusedError";
316768
+ this.code = code;
316769
+ this.remedy = remedy;
316770
+ }
316771
+ };
316772
+ function findAddonRefusal(err) {
316773
+ const seen = /* @__PURE__ */ new Set();
316774
+ let current = err;
316775
+ while (current !== null && current !== void 0 && !seen.has(current)) {
316776
+ if (current instanceof AddonRefusedError) return current;
316777
+ seen.add(current);
316778
+ current = current instanceof Error ? current.cause : void 0;
316779
+ }
316780
+ return null;
316781
+ }
316783
316782
  function createScopedProcessManager(broker, addonId) {
316784
316783
  return {
316785
316784
  async spawn(config) {
@@ -317868,7 +317867,6 @@ var require_dist3 = __commonJS({
317868
317867
  exports.CAP_METHOD_NOT_IMPLEMENTED = CAP_METHOD_NOT_IMPLEMENTED;
317869
317868
  exports.CA_COMMON_NAME = require_agent_https.CA_COMMON_NAME;
317870
317869
  exports.CA_VALIDITY_DAYS = require_agent_https.CA_VALIDITY_DAYS;
317871
- exports.CLUSTER_NODE_HISTORY_COLLECTION = CLUSTER_NODE_HISTORY_COLLECTION;
317872
317870
  exports.CORE_CAP_SERVICE_NAME = CORE_CAP_SERVICE_NAME;
317873
317871
  exports.CalendarsAddon = require_builtins_calendars_calendars_addon.CalendarsAddon;
317874
317872
  exports.CapRouteError = CapRouteError;
@@ -318044,14 +318042,11 @@ var require_dist3 = __commonJS({
318044
318042
  exports.ToastService = ToastService;
318045
318043
  exports.UDS_NO_ROUTE_PREFIX = UDS_NO_ROUTE_PREFIX;
318046
318044
  exports.UNCLAIMED = UNCLAIMED;
318047
- exports.UNMIGRATED_SETTINGS_CODE = UNMIGRATED_SETTINGS_CODE;
318048
- exports.UNMIGRATED_SETTINGS_REMEDY = UNMIGRATED_SETTINGS_REMEDY;
318049
318045
  exports.UPLOADED_CA_FILE = require_hub_mdns_ciao.UPLOADED_CA_FILE;
318050
318046
  exports.USER_MANAGEMENT_INTERNAL = require_builtins_local_auth_local_auth_addon.USER_MANAGEMENT_INTERNAL;
318051
318047
  exports.UdsLocalTransportClient = UdsLocalTransportClient;
318052
318048
  exports.UdsLocalTransportServer = UdsLocalTransportServer;
318053
318049
  exports.UnlockTicketJtiStore = require_builtins_system_config_system_config_addon.UnlockTicketJtiStore;
318054
- exports.UnmigratedSettingsError = UnmigratedSettingsError;
318055
318050
  exports.UserManager = require_builtins_local_auth_local_auth_addon.UserManager;
318056
318051
  exports.WinstonDestination = require_builtins_winston_logging_index.WinstonDestination$1;
318057
318052
  exports.WinstonLoggingAddon = require_builtins_winston_logging_index.WinstonLoggingAddon$1;
@@ -318069,7 +318064,6 @@ var require_dist3 = __commonJS({
318069
318064
  exports.applyCertificateToListener = require_hub_mdns_ciao.applyCertificateToListener;
318070
318065
  exports.applyLanHttp = require_hub_mdns_ciao.applyLanHttp;
318071
318066
  exports.asBrokerLike = asBrokerLike;
318072
- exports.assertLegacyBlobsMigrated = assertLegacyBlobsMigrated;
318073
318067
  exports.attachUserManagementInternal = require_builtins_local_auth_local_auth_addon.attachUserManagementInternal;
318074
318068
  exports.attributeStall = require_custom_action_registry.attributeStall;
318075
318069
  exports.backupOrchestratorRecordKinds = require_restore_archive.backupOrchestratorRecordKinds;
@@ -318701,7 +318695,7 @@ var require_dist4 = __commonJS({
318701
318695
  "../types/dist/index.js"(exports) {
318702
318696
  "use strict";
318703
318697
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
318704
- var require_sleep = require_sleep_gRQc2IoX();
318698
+ var require_sleep = require_sleep_Re8daN0Y();
318705
318699
  var require_event_category = require_event_category_eSqkye_K();
318706
318700
  var require_composition = require_composition_eoYYVfOp();
318707
318701
  var require_node_color2 = require_node_color();
@@ -329231,19 +329225,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
329231
329225
  /** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
329232
329226
  declaration: require_sleep.RecordKindDeclarationSchema
329233
329227
  });
329234
- var STORAGE_ADMIN_MOVED_COLLECTIONS = [
329235
- "stream-broker:probe-snapshots",
329236
- "stream-broker:profile-map",
329237
- "stream-broker:rtsp-tokens",
329238
- "notification-center:device-mutes",
329239
- "recorder:recording-configs",
329240
- "pipeline-orchestrator:device-features"
329241
- ];
329242
- var STORAGE_ADMIN_SCOPED_BASES = [
329243
- "addon-settings",
329244
- "addon-devices",
329245
- "sections"
329246
- ];
329247
329228
  var storageAdminCapability = {
329248
329229
  name: "storage-admin",
329249
329230
  scope: "system",
@@ -329255,26 +329236,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
329255
329236
  * optionally only those owned by `ownerPrefix`. Reads only.
329256
329237
  */
329257
329238
  listTables: require_sleep.method(zod.z.object({ ownerPrefix: zod.z.string().min(1).optional() }), zod.z.object({ tables: zod.z.array(StorageTableSchema) }), { auth: "admin" }),
329258
- /**
329259
- * Drop one table. REFUSES when an addon declared it since the engine
329260
- * started (a running addon still owns it), when it is an engine or
329261
- * canonical table, when it does not exist, or when its row count is not
329262
- * `expectRows` - the caller states what it believes it is deleting. The
329263
- * engine also refuses anything but `<owner>:(addon-settings|addon-devices|
329264
- * sections)`, the retired collections by name, and tables of owners that
329265
- * are not installed (and refuses when it cannot read the installed list).
329266
- * Removed with the D870 migration script once the last hub ran it.
329267
- */
329268
- dropCollection: require_sleep.method(zod.z.object({
329269
- collection: zod.z.string().min(1),
329270
- expectRows: zod.z.number().int().nonnegative()
329271
- }), zod.z.object({
329272
- dropped: zod.z.literal(true),
329273
- rows: zod.z.number().int().nonnegative()
329274
- }), {
329275
- kind: "mutation",
329276
- auth: "admin"
329277
- }),
329278
329239
  /** Every record kind of both files with rows, a size estimate, class and retention (D881). */
329279
329240
  listKinds: require_sleep.method(zod.z.object({
329280
329241
  owner: zod.z.string().min(1).optional(),
@@ -356575,6 +356536,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
356575
356536
  * Replaces `zoneCrop`.
356576
356537
  */
356577
356538
  showTriggerZone: zod.z.boolean().optional(),
356539
+ /**
356540
+ * Draw the SUBJECT'S PATH on the picture — a line in the subject's colour
356541
+ * through the track's positions up to the frame shown, the same path the
356542
+ * debug views draw (`buildSubjectPath`, D903). Every picture mode a subject
356543
+ * is drawn on: a `crop` maps the path into the crop and clips it. Valid only
356544
+ * on a rule whose subject is a tracked object (refused on a sound rule);
356545
+ * dropped on `image: 'none'`. Absent = off.
356546
+ */
356547
+ showSubjectPath: zod.z.boolean().optional(),
356578
356548
  /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
356579
356549
  attach: zod.z.enum([
356580
356550
  "best",
@@ -390230,12 +390200,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
390230
390200
  addonId: null,
390231
390201
  access: "create"
390232
390202
  },
390233
- "storageAdmin.dropCollection": {
390234
- capName: "storage-admin",
390235
- capScope: "system",
390236
- addonId: null,
390237
- access: "delete"
390238
- },
390239
390203
  "storageAdmin.listKinds": {
390240
390204
  capName: "storage-admin",
390241
390205
  capScope: "system",
@@ -400578,15 +400542,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
400578
400542
  return clampToKind(legacyImageMode(media), kind);
400579
400543
  }
400580
400544
  function normalizeNcMediaPolicy(media, rule) {
400581
- const image = resolveNcMediaImage(media, ruleKindOf(rule));
400582
- const { attach: _attach, frame: _frame, zoneCrop, showTriggerZone, image: _image, ...rest } = media;
400545
+ const kind = ruleKindOf(rule);
400546
+ const image = resolveNcMediaImage(media, kind);
400547
+ const { attach: _attach, frame: _frame, zoneCrop, showTriggerZone, showSubjectPath, image: _image, ...rest } = media;
400583
400548
  const drawable = (showTriggerZone === true || media.image === void 0 && zoneCrop === true) && image !== "crop" && image !== "none" && ruleTriggerZoneIds(rule.conditions).length > 0;
400549
+ const pathDrawable = showSubjectPath === true && image !== "none" && subjectHasPath(kind);
400584
400550
  return {
400585
400551
  ...rest,
400586
400552
  image,
400587
- ...drawable ? { showTriggerZone: true } : {}
400553
+ ...drawable ? { showTriggerZone: true } : {},
400554
+ ...pathDrawable ? { showSubjectPath: true } : {}
400588
400555
  };
400589
400556
  }
400557
+ function subjectHasPath(kind) {
400558
+ const spec = ruleKindSpec(kind);
400559
+ return spec.carriesMedia && spec.carriesSubjectCrop;
400560
+ }
400590
400561
  function ncMediaPolicyError(media, rule) {
400591
400562
  const kind = ruleKindOf(rule);
400592
400563
  if (media.image !== void 0) {
@@ -400594,6 +400565,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
400594
400565
  if (offered.length > 0 && !offered.includes(media.image)) return `media.image '${media.image}' is not available for a ${kind} rule (offered: ${offered.join(", ")})`;
400595
400566
  }
400596
400567
  if (media.showTriggerZone === true && ruleTriggerZoneIds(rule.conditions).length === 0) return "media.showTriggerZone needs a rule triggered by a zone (a zones condition or an occupancy zone)";
400568
+ if (media.showSubjectPath === true && !subjectHasPath(kind)) return `media.showSubjectPath needs a rule whose subject is a tracked object (not a ${kind} rule)`;
400597
400569
  return null;
400598
400570
  }
400599
400571
  var WEEKDAY_TO_DAY = {
@@ -400651,17 +400623,181 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
400651
400623
  if (schedule === void 0) return true;
400652
400624
  const { day, minute } = localDayMinute(atMs, schedule.timezone);
400653
400625
  const prevDay = (day + 6) % 7;
400654
- let inside = false;
400626
+ let inside2 = false;
400655
400627
  for (const w of schedule.windows) if (w.startMinute <= w.endMinute) {
400656
400628
  if (w.days.includes(day) && minute >= w.startMinute && minute < w.endMinute) {
400657
- inside = true;
400629
+ inside2 = true;
400658
400630
  break;
400659
400631
  }
400660
400632
  } else if (w.days.includes(day) && minute >= w.startMinute || w.days.includes(prevDay) && minute < w.endMinute) {
400661
- inside = true;
400633
+ inside2 = true;
400662
400634
  break;
400663
400635
  }
400664
- return schedule.invert === true ? !inside : inside;
400636
+ return schedule.invert === true ? !inside2 : inside2;
400637
+ }
400638
+ var SUBJECT_PATH_FULL_FRAME_COVERAGE = 0.85;
400639
+ var SUBJECT_PATH_DWELL_EPS = 5e-3;
400640
+ var SUBJECT_PATH_MAX_POINTS = 120;
400641
+ var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
400642
+ function subjectPathSampleFromBox(bbox, timestamp) {
400643
+ return {
400644
+ x: bbox.x + bbox.w / 2,
400645
+ y: bbox.y + bbox.h / 2,
400646
+ w: bbox.w,
400647
+ h: bbox.h,
400648
+ ...timestamp !== void 0 ? { timestamp } : {}
400649
+ };
400650
+ }
400651
+ function isPlaceholder(s) {
400652
+ return s.w !== void 0 && s.h !== void 0 && s.w >= 0.85 && s.h >= 0.85;
400653
+ }
400654
+ function downsample(xs, max) {
400655
+ if (xs.length <= max || max < 2) return xs;
400656
+ const step = (xs.length - 1) / (max - 1);
400657
+ const out = [];
400658
+ for (let i = 0; i < max - 1; i++) {
400659
+ const x = xs[Math.round(i * step)];
400660
+ if (x !== void 0) out.push(x);
400661
+ }
400662
+ const last = xs[xs.length - 1];
400663
+ if (last !== void 0) out.push(last);
400664
+ return out;
400665
+ }
400666
+ function isFiniteSample(s) {
400667
+ return Number.isFinite(s.x) && Number.isFinite(s.y);
400668
+ }
400669
+ function buildSubjectPath(samples, opts) {
400670
+ const until = opts?.untilTimestamp;
400671
+ const nodes = [];
400672
+ let unlocalized = 0;
400673
+ let tail = null;
400674
+ for (let index = 0; index < samples.length; index++) {
400675
+ const s = samples[index];
400676
+ if (s === void 0 || !isFiniteSample(s)) continue;
400677
+ if (until !== void 0 && s.timestamp !== void 0 && s.timestamp > until) continue;
400678
+ if (isPlaceholder(s)) {
400679
+ unlocalized += 1;
400680
+ continue;
400681
+ }
400682
+ const ts = s.timestamp !== void 0 && Number.isFinite(s.timestamp) ? s.timestamp : index;
400683
+ const x = clamp01(s.x);
400684
+ const y = clamp01(s.y);
400685
+ const prev = nodes[nodes.length - 1];
400686
+ if (prev !== void 0 && Math.hypot(x - prev.x, y - prev.y) < 5e-3) {
400687
+ nodes[nodes.length - 1] = {
400688
+ ...prev,
400689
+ samples: prev.samples + 1,
400690
+ lastTs: Math.max(prev.lastTs, ts)
400691
+ };
400692
+ tail = {
400693
+ x,
400694
+ y,
400695
+ samples: 1,
400696
+ firstTs: ts,
400697
+ lastTs: ts
400698
+ };
400699
+ continue;
400700
+ }
400701
+ tail = null;
400702
+ nodes.push({
400703
+ x,
400704
+ y,
400705
+ samples: 1,
400706
+ firstTs: ts,
400707
+ lastTs: ts
400708
+ });
400709
+ }
400710
+ const end = nodes[nodes.length - 1];
400711
+ if (tail !== null && end !== void 0 && end.samples > 1 && (tail.x !== end.x || tail.y !== end.y)) {
400712
+ nodes[nodes.length - 1] = {
400713
+ ...end,
400714
+ samples: end.samples - 1
400715
+ };
400716
+ nodes.push(tail);
400717
+ }
400718
+ return {
400719
+ nodes: downsample(nodes, opts?.maxPoints ?? 120),
400720
+ unlocalized
400721
+ };
400722
+ }
400723
+ function isDrawableSubjectPath(path) {
400724
+ return path.nodes.length >= 2;
400725
+ }
400726
+ function inside(p) {
400727
+ return p.x >= 0 && p.x <= 1 && p.y >= 0 && p.y <= 1;
400728
+ }
400729
+ function clipSegment(a, b) {
400730
+ const dx = b.x - a.x;
400731
+ const dy = b.y - a.y;
400732
+ let t0 = 0;
400733
+ let t1 = 1;
400734
+ const edges = [
400735
+ [-dx, a.x],
400736
+ [dx, 1 - a.x],
400737
+ [-dy, a.y],
400738
+ [dy, 1 - a.y]
400739
+ ];
400740
+ for (const [p, q] of edges) {
400741
+ if (p === 0) {
400742
+ if (q < 0) return null;
400743
+ continue;
400744
+ }
400745
+ const r = q / p;
400746
+ if (p < 0) {
400747
+ if (r > t1) return null;
400748
+ if (r > t0) t0 = r;
400749
+ } else {
400750
+ if (r < t0) return null;
400751
+ if (r < t1) t1 = r;
400752
+ }
400753
+ }
400754
+ return [{
400755
+ x: a.x + t0 * dx,
400756
+ y: a.y + t0 * dy
400757
+ }, {
400758
+ x: a.x + t1 * dx,
400759
+ y: a.y + t1 * dy
400760
+ }];
400761
+ }
400762
+ function samePoint(a, b) {
400763
+ return Math.abs(a.x - b.x) < 1e-9 && Math.abs(a.y - b.y) < 1e-9;
400764
+ }
400765
+ function projectSubjectPath(points, view) {
400766
+ if (points.length < 2 || !(view.w > 0) || !(view.h > 0)) return [];
400767
+ const local = points.map((p) => ({
400768
+ x: (p.x - view.x) / view.w,
400769
+ y: (p.y - view.y) / view.h
400770
+ }));
400771
+ const runs = [];
400772
+ let run = [];
400773
+ for (let i = 1; i < local.length; i++) {
400774
+ const a = local[i - 1];
400775
+ const b = local[i];
400776
+ if (a === void 0 || b === void 0) continue;
400777
+ const seg = clipSegment(a, b);
400778
+ if (seg === null) {
400779
+ if (run.length >= 2) runs.push(run);
400780
+ run = [];
400781
+ continue;
400782
+ }
400783
+ const [from2, to] = seg;
400784
+ const last = run[run.length - 1];
400785
+ if (last === void 0 || !samePoint(last, from2)) {
400786
+ if (run.length >= 2) runs.push(run);
400787
+ run = [from2];
400788
+ }
400789
+ run.push(to);
400790
+ if (!inside(b)) {
400791
+ if (run.length >= 2) runs.push(run);
400792
+ run = [];
400793
+ }
400794
+ }
400795
+ if (run.length >= 2) runs.push(run);
400796
+ return runs;
400797
+ }
400798
+ function subjectPathSvgPoints(run, width, height) {
400799
+ const fmt = (v) => String(Math.round(v * 100) / 100);
400800
+ return run.map((p) => `${fmt(p.x * width)},${fmt(p.y * height)}`).join(" ");
400665
400801
  }
400666
400802
  var ARMED_WORD_PREFIX = "armed_";
400667
400803
  var ALARM_PANEL_CAP = "alarm-panel";
@@ -406102,14 +406238,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406102
406238
  }
406103
406239
  function pointInPolygon(point, polygon) {
406104
406240
  if (polygon.length < 3) return false;
406105
- let inside = false;
406241
+ let inside2 = false;
406106
406242
  const { x, y } = point;
406107
406243
  for (let i = 0, j2 = polygon.length - 1; i < polygon.length; j2 = i++) {
406108
406244
  const a = polygon[i];
406109
406245
  const b = polygon[j2];
406110
- if (a.y > y !== b.y > y && x < (b.x - a.x) * (y - a.y) / (b.y - a.y || Number.EPSILON) + a.x) inside = !inside;
406246
+ if (a.y > y !== b.y > y && x < (b.x - a.x) * (y - a.y) / (b.y - a.y || Number.EPSILON) + a.x) inside2 = !inside2;
406111
406247
  }
406112
- return inside;
406248
+ return inside2;
406113
406249
  }
406114
406250
  function bindAddonActions(api, addonId, catalog) {
406115
406251
  const out = {};
@@ -408042,12 +408178,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408042
408178
  exports.STATE_LABEL_KEYS = STATE_LABEL_KEYS;
408043
408179
  exports.STATIONARY_OVERLAY_STYLE = STATIONARY_OVERLAY_STYLE;
408044
408180
  exports.STORAGE_ACCESS_FALLBACK = STORAGE_ACCESS_FALLBACK;
408045
- exports.STORAGE_ADMIN_MOVED_COLLECTIONS = STORAGE_ADMIN_MOVED_COLLECTIONS;
408046
- exports.STORAGE_ADMIN_SCOPED_BASES = STORAGE_ADMIN_SCOPED_BASES;
408047
408181
  exports.STORAGE_BYTES_PER_GB = STORAGE_BYTES_PER_GB;
408048
408182
  exports.STORAGE_LOCATION_MODES = STORAGE_LOCATION_MODES;
408049
408183
  exports.STREAM_PROFILE_META = STREAM_PROFILE_META;
408050
408184
  exports.STREAM_QUALITY_LABELS = STREAM_QUALITY_LABELS;
408185
+ exports.SUBJECT_PATH_DWELL_EPS = SUBJECT_PATH_DWELL_EPS;
408186
+ exports.SUBJECT_PATH_FULL_FRAME_COVERAGE = SUBJECT_PATH_FULL_FRAME_COVERAGE;
408187
+ exports.SUBJECT_PATH_MAX_POINTS = SUBJECT_PATH_MAX_POINTS;
408051
408188
  exports.SUB_DETECTION_TYPES = SUB_DETECTION_TYPES;
408052
408189
  exports.SYSTEM_CAP_NAMES = SYSTEM_CAP_NAMES;
408053
408190
  exports.SYSTEM_SCOPE_DEVICE_METHODS = SYSTEM_SCOPE_DEVICE_METHODS;
@@ -408439,6 +408576,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408439
408576
  exports.buildRoleScopes = buildRoleScopes;
408440
408577
  exports.buildSecretRef = require_sleep.buildSecretRef;
408441
408578
  exports.buildStreamParamsConfigSchema = buildStreamParamsConfigSchema;
408579
+ exports.buildSubjectPath = buildSubjectPath;
408442
408580
  exports.buildVideoArgs = require_composition.buildVideoArgs;
408443
408581
  exports.buildViewerLink = buildViewerLink;
408444
408582
  exports.builtCapabilityBlockers = builtCapabilityBlockers;
@@ -408760,6 +408898,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408760
408898
  exports.isDeviceScopedCap = require_sleep.isDeviceScopedCap;
408761
408899
  exports.isDoActionActuatable = isDoActionActuatable;
408762
408900
  exports.isDoPickerDeviceType = isDoPickerDeviceType;
408901
+ exports.isDrawableSubjectPath = isDrawableSubjectPath;
408763
408902
  exports.isEmbeddingModelFailed = isEmbeddingModelFailed;
408764
408903
  exports.isEvent = require_sleep.isEvent;
408765
408904
  exports.isEventKindLabelKey = isEventKindLabelKey;
@@ -408973,6 +409112,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408973
409112
  exports.principalMayReachAddon = principalMayReachAddon;
408974
409113
  exports.privacyMaskCapability = privacyMaskCapability;
408975
409114
  exports.procedureAuthKey = procedureAuthKey;
409115
+ exports.projectSubjectPath = projectSubjectPath;
408976
409116
  exports.providerMotionEvent = providerMotionEvent;
408977
409117
  exports.ptzAutotrackCapability = ptzAutotrackCapability;
408978
409118
  exports.ptzCapability = ptzCapability;
@@ -409152,6 +409292,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
409152
409292
  exports.stripRetiredBandPreBufferSec = stripRetiredBandPreBufferSec;
409153
409293
  exports.strippedOfLegacyReadOnly = strippedOfLegacyReadOnly;
409154
409294
  exports.subKindsOf = subKindsOf;
409295
+ exports.subjectHasPath = subjectHasPath;
409296
+ exports.subjectPathSampleFromBox = subjectPathSampleFromBox;
409297
+ exports.subjectPathSvgPoints = subjectPathSvgPoints;
409155
409298
  exports.summarisePrivacyAudio = summarisePrivacyAudio;
409156
409299
  exports.summarizeEffectiveScope = summarizeEffectiveScope;
409157
409300
  exports.summarizeReview = summarizeReview;
@@ -590921,10 +591064,6 @@ var require_addon_registry_service = __commonJS({
590921
591064
  plannedRunnerIds() {
590922
591065
  return [...this.buildAddonGroupPlan([...this.addonEntries.keys()]).keys()];
590923
591066
  }
590924
- /** The forked addon ids (the ones whose Init the D870 guard gates). */
590925
- forkedAddonIds() {
590926
- return [...this.buildAddonGroupPlan([...this.addonEntries.keys()]).values()].flatMap((roster) => roster.map((r) => r.addonId));
590927
- }
590928
591067
  /**
590929
591068
  * Snapshot of the live runner subprocesses (`$process.list`), reduced to the
590930
591069
  * `{ runnerId, addonIds }` shape the convergence planner needs. Returns `[]`
@@ -595515,7 +595654,6 @@ var require_cluster_node_history_store = __commonJS({
595515
595654
  lastActive: zod_1.z.number(),
595516
595655
  descriptor: DescriptorSchema
595517
595656
  });
595518
- var COLLECTION = "cluster-node-history";
595519
595657
  var LAST_ACTIVE_HEARTBEAT_MS = 5 * 6e4;
595520
595658
  function descriptorsEqual(a, b) {
595521
595659
  return a.id === b.id && a.name === b.name && a.hostname === b.hostname && a.platform === b.platform && a.arch === b.arch && a.cpuModel === b.cpuModel && a.cpuCores === b.cpuCores && a.memoryMB === b.memoryMB && a.isHub === b.isHub && sameStrings(a.engines, b.engines) && sameStrings(a.localIps, b.localIps) && sameStrings(a.addonIds, b.addonIds) && samePackages(a.packages, b.packages);
@@ -595529,12 +595667,9 @@ var require_cluster_node_history_store = __commonJS({
595529
595667
  return a.length === b.length && a.every((p, i) => p.name === b[i]?.name && p.version === b[i]?.version);
595530
595668
  }
595531
595669
  var ClusterNodeHistoryStore = class _ClusterNodeHistoryStore {
595532
- resolveSettingsStore;
595533
595670
  logger;
595534
- declared = false;
595535
595671
  resolveKind;
595536
- constructor(resolveSettingsStore, logger, resolveKind = () => null) {
595537
- this.resolveSettingsStore = resolveSettingsStore;
595672
+ constructor(logger, resolveKind = () => null) {
595538
595673
  this.logger = logger;
595539
595674
  this.resolveKind = resolveKind;
595540
595675
  }
@@ -595542,37 +595677,6 @@ var require_cluster_node_history_store = __commonJS({
595542
595677
  bindRecordsKind(resolver) {
595543
595678
  this.resolveKind = resolver;
595544
595679
  }
595545
- /**
595546
- * Idempotently declare the typed collection. Returns the resolved provider
595547
- * or null if the settings-store isn't available yet (early boot / hub
595548
- * unreachable) — callers treat null as "skip, best-effort".
595549
- */
595550
- async ensureDeclared() {
595551
- if (this.resolveKind() !== null)
595552
- return this.resolveSettingsStore();
595553
- const store = this.resolveSettingsStore();
595554
- if (!store)
595555
- return null;
595556
- if (this.declared)
595557
- return store;
595558
- try {
595559
- await store.declareCollection({
595560
- collection: COLLECTION,
595561
- columns: [
595562
- { name: "id", type: "TEXT", primaryKey: true, notNull: true },
595563
- { name: "lastActive", type: "INTEGER", notNull: true },
595564
- { name: "descriptor", type: "JSON", notNull: true }
595565
- ]
595566
- });
595567
- this.declared = true;
595568
- return store;
595569
- } catch (err) {
595570
- this.logger.warn("declareCollection failed (best-effort)", {
595571
- meta: { error: (0, types_1.errMsg)(err) }
595572
- });
595573
- return null;
595574
- }
595575
- }
595576
595680
  /**
595577
595681
  * Upsert a node's descriptor + addon roster while it is ONLINE, stamping
595578
595682
  * `lastActive = Date.now()`. Called on each `listNodes()` refresh for every
@@ -595592,16 +595696,16 @@ var require_cluster_node_history_store = __commonJS({
595592
595696
  * `$node.disconnected`, and buys 288 writes/day/node instead of 2,880.
595593
595697
  */
595594
595698
  async snapshot(descriptor) {
595595
- const store = await this.ensureDeclared();
595596
- if (!store)
595699
+ const kind = this.resolveKind();
595700
+ if (kind === null)
595597
595701
  return;
595598
595702
  try {
595599
- const existing = await this.readStored(descriptor.id);
595703
+ const existing = await this.readStored(kind, descriptor.id);
595600
595704
  const packages = descriptor.packages ?? existing?.descriptor.packages;
595601
595705
  const next = packages === void 0 ? descriptor : { ...descriptor, packages };
595602
595706
  if (existing !== null && !this.worthWriting(existing, next))
595603
595707
  return;
595604
- await this.writeStored(descriptor.id, Date.now(), next);
595708
+ await this.writeStored(kind, descriptor.id, Date.now(), next);
595605
595709
  } catch (err) {
595606
595710
  this.logger.warn("snapshot upsert failed (best-effort)", {
595607
595711
  tags: { nodeId: descriptor.id },
@@ -595620,47 +595724,21 @@ var require_cluster_node_history_store = __commonJS({
595620
595724
  return !descriptorsEqual(existing.descriptor, next);
595621
595725
  }
595622
595726
  /** Read one node's row, validated. `null` when absent or malformed. */
595623
- async readStored(nodeId) {
595624
- const kind = this.resolveKind();
595625
- if (kind !== null) {
595626
- const row = await kind.get(nodeId);
595627
- if (row === null)
595628
- return null;
595629
- const parsed = RowDataSchema.safeParse({
595630
- lastActive: row.at ?? 0,
595631
- descriptor: row.data.descriptor
595632
- });
595633
- return parsed.success ? parsed.data : null;
595634
- }
595635
- const store = this.resolveSettingsStore();
595636
- if (!store)
595637
- return null;
595638
- return this.readRowLegacy(store, nodeId);
595639
- }
595640
- async readRowLegacy(store, nodeId) {
595641
- const raw = await store.get({ collection: COLLECTION, key: nodeId });
595642
- if (raw === null || raw === void 0)
595727
+ async readStored(kind, nodeId) {
595728
+ const row = await kind.get(nodeId);
595729
+ if (row === null)
595643
595730
  return null;
595644
- const parsed = RowDataSchema.safeParse(raw);
595731
+ const parsed = RowDataSchema.safeParse({
595732
+ lastActive: row.at ?? 0,
595733
+ descriptor: row.data.descriptor
595734
+ });
595645
595735
  return parsed.success ? parsed.data : null;
595646
595736
  }
595647
- async writeStored(nodeId, lastActive, descriptor) {
595648
- const kind = this.resolveKind();
595649
- if (kind !== null) {
595650
- const body = system_1.ClusterNodeHistoryBodySchema.safeParse({ descriptor });
595651
- if (!body.success)
595652
- return;
595653
- await kind.put({ id: nodeId, at: lastActive, data: body.data });
595654
- return;
595655
- }
595656
- const store = this.resolveSettingsStore();
595657
- if (!store)
595737
+ async writeStored(kind, nodeId, lastActive, descriptor) {
595738
+ const body = system_1.ClusterNodeHistoryBodySchema.safeParse({ descriptor });
595739
+ if (!body.success)
595658
595740
  return;
595659
- await store.set({
595660
- collection: COLLECTION,
595661
- key: nodeId,
595662
- value: { lastActive, descriptor }
595663
- });
595741
+ await kind.put({ id: nodeId, at: lastActive, data: body.data });
595664
595742
  }
595665
595743
  /** A placeholder descriptor for a node the topology pass has not seen yet. */
595666
595744
  static placeholderDescriptor(nodeId) {
@@ -595685,11 +595763,11 @@ var require_cluster_node_history_store = __commonJS({
595685
595763
  * nothing is delivered rather than something guessed.
595686
595764
  */
595687
595765
  async getPackages(nodeId) {
595688
- const store = await this.ensureDeclared();
595689
- if (!store)
595766
+ const kind = this.resolveKind();
595767
+ if (kind === null)
595690
595768
  return [];
595691
595769
  try {
595692
- return (await this.readStored(nodeId))?.descriptor.packages ?? [];
595770
+ return (await this.readStored(kind, nodeId))?.descriptor.packages ?? [];
595693
595771
  } catch (err) {
595694
595772
  this.logger.warn("getPackages failed (best-effort)", {
595695
595773
  tags: { nodeId },
@@ -595709,11 +595787,11 @@ var require_cluster_node_history_store = __commonJS({
595709
595787
  async recordPackages(nodeId, packages) {
595710
595788
  if (packages.length === 0)
595711
595789
  return;
595712
- const store = await this.ensureDeclared();
595713
- if (!store)
595790
+ const kind = this.resolveKind();
595791
+ if (kind === null)
595714
595792
  return;
595715
595793
  try {
595716
- const existing = await this.readStored(nodeId);
595794
+ const existing = await this.readStored(kind, nodeId);
595717
595795
  const merged = new Map((existing?.descriptor.packages ?? []).map((p) => [p.name, p]));
595718
595796
  for (const entry of packages)
595719
595797
  merged.set(entry.name, entry);
@@ -595721,7 +595799,7 @@ var require_cluster_node_history_store = __commonJS({
595721
595799
  ...existing?.descriptor ?? _ClusterNodeHistoryStore.placeholderDescriptor(nodeId),
595722
595800
  packages: [...merged.values()]
595723
595801
  };
595724
- await this.writeStored(nodeId, existing?.lastActive ?? Date.now(), descriptor);
595802
+ await this.writeStored(kind, nodeId, existing?.lastActive ?? Date.now(), descriptor);
595725
595803
  } catch (err) {
595726
595804
  this.logger.warn("recordPackages failed (best-effort)", {
595727
595805
  tags: { nodeId },
@@ -595737,11 +595815,11 @@ var require_cluster_node_history_store = __commonJS({
595737
595815
  async prunePackages(nodeId, names) {
595738
595816
  if (names.length === 0)
595739
595817
  return;
595740
- const store = await this.ensureDeclared();
595741
- if (!store)
595818
+ const kind = this.resolveKind();
595819
+ if (kind === null)
595742
595820
  return;
595743
595821
  try {
595744
- const existing = await this.readStored(nodeId);
595822
+ const existing = await this.readStored(kind, nodeId);
595745
595823
  if (existing === null)
595746
595824
  return;
595747
595825
  const current = existing.descriptor.packages;
@@ -595751,7 +595829,7 @@ var require_cluster_node_history_store = __commonJS({
595751
595829
  const remaining = current.filter((p) => !drop.has(p.name));
595752
595830
  if (remaining.length === current.length)
595753
595831
  return;
595754
- await this.writeStored(nodeId, existing.lastActive, {
595832
+ await this.writeStored(kind, nodeId, existing.lastActive, {
595755
595833
  ...existing.descriptor,
595756
595834
  packages: remaining
595757
595835
  });
@@ -595772,27 +595850,14 @@ var require_cluster_node_history_store = __commonJS({
595772
595850
  * time. A no-op if the node was never snapshotted (nothing to update).
595773
595851
  */
595774
595852
  async touch(nodeId) {
595775
- const store = await this.ensureDeclared();
595776
- if (!store)
595853
+ const kind = this.resolveKind();
595854
+ if (kind === null)
595777
595855
  return;
595778
595856
  try {
595779
- const existing = await this.readStored(nodeId);
595857
+ const existing = await this.readStored(kind, nodeId);
595780
595858
  if (existing === null)
595781
595859
  return;
595782
- const kind = this.resolveKind();
595783
- if (kind !== null) {
595784
- await kind.put({
595785
- id: nodeId,
595786
- at: Date.now(),
595787
- data: { descriptor: existing.descriptor }
595788
- });
595789
- return;
595790
- }
595791
- await store.update({
595792
- collection: COLLECTION,
595793
- id: nodeId,
595794
- data: { lastActive: Date.now() }
595795
- });
595860
+ await this.writeStored(kind, nodeId, Date.now(), existing.descriptor);
595796
595861
  } catch (err) {
595797
595862
  this.logger.warn("touch failed (best-effort)", {
595798
595863
  tags: { nodeId },
@@ -595806,24 +595871,20 @@ var require_cluster_node_history_store = __commonJS({
595806
595871
  }
595807
595872
  /**
595808
595873
  * Read the full persisted history, validated, or `null` when the store did
595809
- * not ANSWER (unavailable, or the query threw). A caller that must not claim
595874
+ * not ANSWER (the kind is not bound yet, or the read threw). A caller that must not claim
595810
595875
  * a node absent from an unanswered read (D315) uses this; `getAll` folds the
595811
595876
  * `null` into `[]` for the callers that only render what exists. Malformed
595812
595877
  * rows are dropped (and logged) — the rest of the answer still stands.
595813
595878
  */
595814
595879
  async tryGetAll() {
595815
- const store = await this.ensureDeclared();
595816
- if (!store)
595880
+ const kind = this.resolveKind();
595881
+ if (kind === null)
595817
595882
  return null;
595818
595883
  try {
595819
- const kind = this.resolveKind();
595820
595884
  const result = [];
595821
- const rows = kind !== null ? (await (0, system_1.readAllRows)(kind)).map((row) => ({
595885
+ const rows = (await (0, system_1.readAllRows)(kind)).map((row) => ({
595822
595886
  id: row.id,
595823
595887
  data: { lastActive: row.at ?? 0, descriptor: row.data.descriptor }
595824
- })) : (await store.query({ collection: COLLECTION })).map((row) => ({
595825
- id: row.id,
595826
- data: row.data
595827
595888
  }));
595828
595889
  for (const row of rows) {
595829
595890
  const parsed = RowDataSchema.safeParse(row.data);
@@ -595850,17 +595911,12 @@ var require_cluster_node_history_store = __commonJS({
595850
595911
  * 2026-09-01 all three reached the UI as `{"success": true}`.
595851
595912
  */
595852
595913
  async forget(nodeId) {
595853
- const store = await this.ensureDeclared();
595854
- if (!store)
595914
+ const kind = this.resolveKind();
595915
+ if (kind === null)
595855
595916
  return "store-unavailable";
595856
595917
  try {
595857
- const existed = await this.readStored(nodeId) !== null;
595858
- const kind = this.resolveKind();
595859
- if (kind !== null) {
595860
- await kind.delete(nodeId);
595861
- } else {
595862
- await store.delete({ collection: COLLECTION, key: nodeId });
595863
- }
595918
+ const existed = await this.readStored(kind, nodeId) !== null;
595919
+ await kind.delete(nodeId);
595864
595920
  if (!existed) {
595865
595921
  this.logger.info("cluster node had no history row to forget", { tags: { nodeId } });
595866
595922
  return "not-found";
@@ -595997,52 +596053,6 @@ var require_toast_wrapper_service = __commonJS({
595997
596053
  }
595998
596054
  });
595999
596055
 
596000
- // ../../server/backend/dist/core/runner-health/update-preflight.js
596001
- var require_update_preflight = __commonJS({
596002
- "../../server/backend/dist/core/runner-health/update-preflight.js"(exports) {
596003
- "use strict";
596004
- Object.defineProperty(exports, "__esModule", { value: true });
596005
- exports.LEGACY_BLOB_GUARD_SINCE = void 0;
596006
- exports.buildUpdatePreflight = buildUpdatePreflight;
596007
- exports.legacyGuardClientOf = legacyGuardClientOf;
596008
- var system_1 = require_dist3();
596009
- var index_js_1 = require_server_root();
596010
- exports.LEGACY_BLOB_GUARD_SINCE = "1.2.585";
596011
- function buildUpdatePreflight(deps) {
596012
- return async (targetVersion) => {
596013
- if ((0, index_js_1.compareSemver)(targetVersion, exports.LEGACY_BLOB_GUARD_SINCE) < 0)
596014
- return [];
596015
- const store = deps.store();
596016
- if (store === null) {
596017
- throw new Error("the settings store is not available to pre-check the update");
596018
- }
596019
- const blockers = [];
596020
- for (const addonId of deps.forkedAddonIds()) {
596021
- try {
596022
- await (0, system_1.assertLegacyBlobsMigrated)(store, addonId, deps.logger);
596023
- } catch (err) {
596024
- if (!(err instanceof system_1.UnmigratedSettingsError))
596025
- throw err;
596026
- blockers.push({
596027
- addonId,
596028
- reason: err.message,
596029
- remedy: system_1.UNMIGRATED_SETTINGS_REMEDY
596030
- });
596031
- }
596032
- }
596033
- return blockers;
596034
- };
596035
- }
596036
- function legacyGuardClientOf(store) {
596037
- return {
596038
- query: { query: (input) => store.query(input) },
596039
- get: { query: (input) => store.get(input) },
596040
- count: { query: (input) => store.count(input) }
596041
- };
596042
- }
596043
- }
596044
- });
596045
-
596046
596056
  // ../../server/backend/dist/core/topology/topology-emitter.service.js
596047
596057
  var require_topology_emitter_service = __commonJS({
596048
596058
  "../../server/backend/dist/core/topology/topology-emitter.service.js"(exports) {
@@ -596272,7 +596282,6 @@ var require_manual_boot = __commonJS({
596272
596282
  var repl_engine_service_1 = require_repl_engine_service();
596273
596283
  var server_update_service_1 = require_server_update_service();
596274
596284
  var runner_boot_check_1 = require_runner_boot_check();
596275
- var update_preflight_1 = require_update_preflight();
596276
596285
  var storage_service_1 = require_storage_service();
596277
596286
  var stream_probe_service_1 = require_stream_probe_service();
596278
596287
  var topology_emitter_service_1 = require_topology_emitter_service();
@@ -596326,7 +596335,7 @@ var require_manual_boot = __commonJS({
596326
596335
  const addonRegistryService = new addon_registry_service_1.AddonRegistryService(loggingService, eventBusService, configService, storageService, capabilityService, moleculerService, streamProbeService);
596327
596336
  agentRegistryService.setAddonRegistry(addonRegistryService);
596328
596337
  agentRegistryService.setLogger(loggingService.createLogger("ClusterNodes"));
596329
- const clusterNodeHistoryStore = new cluster_node_history_store_1.ClusterNodeHistoryStore(() => capabilityService.getRegistry()?.getSingleton("settings-store") ?? null, loggingService.createLogger("cluster-node-history"));
596338
+ const clusterNodeHistoryStore = new cluster_node_history_store_1.ClusterNodeHistoryStore(loggingService.createLogger("cluster-node-history"));
596330
596339
  agentRegistryService.setClusterNodeHistoryStore(clusterNodeHistoryStore);
596331
596340
  addonRegistryService.setClusterNodeHistoryStore(clusterNodeHistoryStore);
596332
596341
  const addonWidgetsService = new addon_widgets_service_1.AddonWidgetsService(loggingService, capabilityService, addonRegistryService);
@@ -596412,16 +596421,7 @@ var require_manual_boot = __commonJS({
596412
596421
  });
596413
596422
  }
596414
596423
  });
596415
- const settingsStoreOrNull = () => capabilityService.getRegistry()?.getSingleton("settings-store") ?? null;
596416
596424
  const serverUpdateService = new server_update_service_1.ServerUpdateService({
596417
- updatePreflight: (0, update_preflight_1.buildUpdatePreflight)({
596418
- logger: loggingService.createLogger("UpdatePreflight"),
596419
- forkedAddonIds: () => addonRegistryService.forkedAddonIds(),
596420
- store: () => {
596421
- const store = settingsStoreOrNull();
596422
- return store === null ? null : (0, update_preflight_1.legacyGuardClientOf)(store);
596423
- }
596424
- }),
596425
596425
  runnerBootCheck: () => hubRunnerBootCheck.current(),
596426
596426
  logger: loggingService.createLogger("ServerUpdate"),
596427
596427
  restartServer: (requestedBy, update) => addonPackageService.restartServer(requestedBy, update),