camstack 1.2.201 → 1.2.203

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-D9aw_d0G.js
24028
- var require_dist_D9aw_d0G = __commonJS({
24029
- "../system/dist/dist-D9aw_d0G.js"(exports) {
24027
+ // ../system/dist/dist-QyW9hVO2.js
24028
+ var require_dist_QyW9hVO2 = __commonJS({
24029
+ "../system/dist/dist-QyW9hVO2.js"(exports) {
24030
24030
  "use strict";
24031
24031
  var zod = require_zod();
24032
24032
  __require("crypto");
@@ -24110,6 +24110,8 @@ var require_dist_D9aw_d0G = __commonJS({
24110
24110
  EventCategory2["PipelineCameraUnassigned"] = "pipeline.camera-unassigned";
24111
24111
  EventCategory2["PipelineNodeInferenceUnavailable"] = "pipeline.node-inference-unavailable";
24112
24112
  EventCategory2["PipelineDetectionBlind"] = "pipeline.detection-blind";
24113
+ EventCategory2["PipelineMotionNoisy"] = "pipeline.motion-noisy";
24114
+ EventCategory2["PipelineMotionCalm"] = "pipeline.motion-calm";
24113
24115
  EventCategory2["PipelineCameraUpdated"] = "pipeline.camera-updated";
24114
24116
  EventCategory2["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
24115
24117
  EventCategory2["PipelineRunnerLoadSnapshot"] = "pipeline.runner-load-snapshot";
@@ -24182,6 +24184,8 @@ var require_dist_D9aw_d0G = __commonJS({
24182
24184
  EventCategory2["BackupRestored"] = "backup.restored";
24183
24185
  EventCategory2["NotificationDispatched"] = "notification.dispatched";
24184
24186
  EventCategory2["NotificationFailed"] = "notification.failed";
24187
+ EventCategory2["NotificationRuleBroken"] = "notification.rule-broken";
24188
+ EventCategory2["NotificationRuleRepaired"] = "notification.rule-repaired";
24185
24189
  EventCategory2["DeviceUpdated"] = "device.updated";
24186
24190
  EventCategory2["DeviceOnline"] = "device.online";
24187
24191
  EventCategory2["DeviceOffline"] = "device.offline";
@@ -26473,6 +26477,12 @@ var require_dist_D9aw_d0G = __commonJS({
26473
26477
  this.name = "BatchTooLargeError";
26474
26478
  }
26475
26479
  };
26480
+ var TransactRefusedError = class extends RecordsError {
26481
+ constructor(detail) {
26482
+ super("transact-refused", detail);
26483
+ this.name = "TransactRefusedError";
26484
+ }
26485
+ };
26476
26486
  function defOf(schema) {
26477
26487
  const zodBag = Reflect.get(schema, "_zod");
26478
26488
  if (typeof zodBag !== "object" || zodBag === null) return {};
@@ -26653,7 +26663,7 @@ var require_dist_D9aw_d0G = __commonJS({
26653
26663
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
26654
26664
  fields: zod.z.record(zod.z.string(), zod.z.unknown())
26655
26665
  }).strict();
26656
- var RecordKindDeclarationSchema = zod.z.object({
26666
+ var RecordKindDeclarationShape = zod.z.object({
26657
26667
  database: zod.z.enum(RECORD_DATABASES).default("settings"),
26658
26668
  class: zod.z.enum(RECORD_CLASSES),
26659
26669
  writeTrigger: zod.z.string().min(1),
@@ -26671,18 +26681,12 @@ var require_dist_D9aw_d0G = __commonJS({
26671
26681
  secretPaths: zod.z.array(zod.z.string().min(1)).default([]),
26672
26682
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
26673
26683
  secretArrayKeys: zod.z.record(zod.z.string(), zod.z.string()).default({}),
26674
- /**
26675
- * RETIRED (D900): the legacy table a kind adopted from during the records
26676
- * migration. Nothing declares it any more and nothing reads it; the schema
26677
- * still ACCEPTS it because the catalog rows the migration wrote carry it
26678
- * (an orphaned kind is never redeclared) and an addon built before the
26679
- * removal still sends it. Never set it.
26680
- */
26681
- adoptsFrom: zod.z.string().min(1).optional(),
26682
26684
  /** Kinds that must agree through `transact` sit in one file under one family name. */
26683
26685
  transactFamily: zod.z.string().min(1).optional(),
26684
26686
  entry: EntryDescriptorSchema.optional()
26685
- }).strict();
26687
+ });
26688
+ var RecordKindDeclarationSchema = RecordKindDeclarationShape.strict();
26689
+ var StoredRecordKindDeclarationSchema = RecordKindDeclarationShape;
26686
26690
  var RecordKindNameSchema = zod.z.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
26687
26691
  function assertValidDeclaration(name, decl) {
26688
26692
  const refuse = (why) => {
@@ -26760,6 +26764,16 @@ var require_dist_D9aw_d0G = __commonJS({
26760
26764
  }
26761
26765
  return out;
26762
26766
  }
26767
+ function assertTransactScope(members) {
26768
+ const byKind = /* @__PURE__ */ new Map();
26769
+ for (const m of members) byKind.set(m.kind, m);
26770
+ const kinds = [...byKind.values()];
26771
+ if (new Set(kinds.map((m) => m.declaration.database)).size > 1) throw new TransactRefusedError(`cross-file: the ops span more than one database file (${kinds.map((m) => `${m.kind}@${m.declaration.database}`).join(", ")}); a transaction lives in ONE file`);
26772
+ if (kinds.length <= 1) return;
26773
+ const missing = kinds.filter((m) => m.declaration.transactFamily === void 0);
26774
+ if (missing.length > 0) throw new TransactRefusedError(`no-family: ${missing.map((m) => m.kind).join(", ")} declare no transactFamily; kinds that must agree through transact share one`);
26775
+ if (new Set(kinds.map((m) => m.declaration.transactFamily)).size > 1) throw new TransactRefusedError(`cross-family: the ops span more than one transactFamily (${kinds.map((m) => `${m.kind}=${String(m.declaration.transactFamily)}`).join(", ")})`);
26776
+ }
26763
26777
  var CamProfileSchema = zod.z.enum([
26764
26778
  "high",
26765
26779
  "mid",
@@ -31482,17 +31496,6 @@ var require_dist_D9aw_d0G = __commonJS({
31482
31496
  createdAt: zod.z.number(),
31483
31497
  updatedAt: zod.z.number()
31484
31498
  });
31485
- var ApiKeyRecordSchema = zod.z.object({
31486
- id: zod.z.string(),
31487
- label: zod.z.string(),
31488
- isAdmin: zod.z.boolean().default(false),
31489
- allowedProviders: AllowedProviderSchema,
31490
- allowedDevices: AllowedDevicesSchema,
31491
- tokenHash: zod.z.string(),
31492
- tokenPrefix: zod.z.string(),
31493
- createdAt: zod.z.number(),
31494
- lastUsedAt: zod.z.number().optional()
31495
- });
31496
31499
  var ScopedTokenSchema = zod.z.object({
31497
31500
  id: zod.z.string(),
31498
31501
  userId: zod.z.string(),
@@ -36856,15 +36859,31 @@ var require_dist_D9aw_d0G = __commonJS({
36856
36859
  var DeclareKindResultSchema = zod.z.object({
36857
36860
  kindId: zod.z.number().int(),
36858
36861
  state: RecordKindStateSchema,
36859
- createdIndexes: zod.z.array(zod.z.string()),
36860
- /**
36861
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
36862
- * it stays on the wire, null, because an addon built before the removal reads
36863
- * an ABSENT field as "adoption pending" and refuses to start.
36864
- */
36865
- adoptionPending: zod.z.null()
36862
+ createdIndexes: zod.z.array(zod.z.string())
36866
36863
  });
36867
36864
  var SecretRefsList = zod.z.array(zod.z.string());
36865
+ var RecordTransactOpSchema = zod.z.discriminatedUnion("op", [
36866
+ zod.z.object({
36867
+ op: zod.z.literal("put"),
36868
+ kind: RecordKindNameSchema,
36869
+ record: RecordInputSchema,
36870
+ ifRev: zod.z.number().int().min(0).optional()
36871
+ }),
36872
+ zod.z.object({
36873
+ op: zod.z.literal("patch"),
36874
+ kind: RecordKindNameSchema,
36875
+ id: RecordIdSchema,
36876
+ data: RecordBodySchema,
36877
+ at: zod.z.number().int().nullable().optional(),
36878
+ expiresAt: zod.z.number().int().nullable().optional(),
36879
+ ifRev: zod.z.number().int().min(1).optional()
36880
+ }),
36881
+ zod.z.object({
36882
+ op: zod.z.literal("delete"),
36883
+ kind: RecordKindNameSchema,
36884
+ id: RecordIdSchema
36885
+ })
36886
+ ]);
36868
36887
  var RecordSecretRefsSchema = zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.string()));
36869
36888
  var recordsCapability = {
36870
36889
  name: "records",
@@ -36996,6 +37015,22 @@ var require_dist_D9aw_d0G = __commonJS({
36996
37015
  kind: "mutation",
36997
37016
  auth: "admin"
36998
37017
  }),
37018
+ /**
37019
+ * Several single-row writes (put / patch / delete) in ONE SQLite transaction:
37020
+ * all land or none does. Every op's kind must sit in one file and share one
37021
+ * `transactFamily` (`records/transact-refused` otherwise). Results are in op order.
37022
+ */
37023
+ transact: method(zod.z.object({ ops: zod.z.array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), zod.z.object({
37024
+ results: zod.z.array(zod.z.object({
37025
+ rev: zod.z.number().int().nullable(),
37026
+ deleted: zod.z.boolean()
37027
+ })),
37028
+ releasedRefs: SecretRefsList,
37029
+ secretRefs: SecretRefsList
37030
+ }), {
37031
+ kind: "mutation",
37032
+ auth: "admin"
37033
+ }),
36999
37034
  /** The D865 hook body: every kind of this addon declared `deviceRemoval: 'delete'`. */
37000
37035
  deleteDevice: method(zod.z.object({
37001
37036
  deviceId: zod.z.number().int(),
@@ -63092,9 +63127,13 @@ var require_dist_D9aw_d0G = __commonJS({
63092
63127
  "node-updating",
63093
63128
  "node-inference-unavailable",
63094
63129
  "detection-blind",
63130
+ "motion-noisy",
63131
+ "motion-calm",
63095
63132
  "recording-stalled",
63096
63133
  "recording-healthy",
63097
63134
  "recording-degraded",
63135
+ "device-attention-required",
63136
+ "device-attention-resolved",
63098
63137
  "storage-location-low",
63099
63138
  "storage-location-critical",
63100
63139
  "storage-location-ok",
@@ -63118,6 +63157,8 @@ var require_dist_D9aw_d0G = __commonJS({
63118
63157
  "alert-critical",
63119
63158
  "alert-error",
63120
63159
  "alert-critical-resolved",
63160
+ "rule-broken",
63161
+ "rule-repaired",
63121
63162
  "camera-online",
63122
63163
  "camera-offline",
63123
63164
  "camera-disabled",
@@ -76533,6 +76574,16 @@ var require_dist_D9aw_d0G = __commonJS({
76533
76574
  powerState: zod.z.string().nullable(),
76534
76575
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
76535
76576
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
76577
+ /**
76578
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
76579
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
76580
+ * when none is reported. A cleared reminder is not an unknown one.
76581
+ */
76582
+ filterCleaningDue: zod.z.boolean().nullable(),
76583
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
76584
+ machineCareDue: zod.z.boolean().nullable(),
76585
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
76586
+ machineCareRemainingRuns: zod.z.number().int().nonnegative().nullable(),
76536
76587
  /** Option states: null when the appliance does not expose the option or has not said. */
76537
76588
  halfLoad: zod.z.boolean().nullable(),
76538
76589
  hygienePlus: zod.z.boolean().nullable(),
@@ -84659,16 +84710,6 @@ var require_dist_D9aw_d0G = __commonJS({
84659
84710
  allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])).optional(),
84660
84711
  scopes: zod.z.array(TokenScopeSchema).optional()
84661
84712
  });
84662
- var ApiKeySummarySchema = zod.z.object({
84663
- id: zod.z.string(),
84664
- label: zod.z.string(),
84665
- isAdmin: zod.z.boolean().default(false),
84666
- allowedProviders: zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")]).optional(),
84667
- allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])).optional(),
84668
- tokenPrefix: zod.z.string(),
84669
- createdAt: zod.z.number(),
84670
- lastUsedAt: zod.z.number().optional()
84671
- });
84672
84713
  var OauthSessionSummarySchema = zod.z.object({
84673
84714
  id: zod.z.string(),
84674
84715
  userId: zod.z.string(),
@@ -84749,12 +84790,6 @@ var require_dist_D9aw_d0G = __commonJS({
84749
84790
  kind: "mutation",
84750
84791
  access: "view"
84751
84792
  }),
84752
- listApiKeys: method(zod.z.void(), zod.z.array(ApiKeySummarySchema), { auth: "admin" }),
84753
- revokeApiKey: method(zod.z.object({ id: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
84754
- kind: "mutation",
84755
- auth: "admin",
84756
- access: "delete"
84757
- }),
84758
84793
  setupTotp: method(zod.z.object({ userId: zod.z.string() }), TotpSetupResultSchema, {
84759
84794
  kind: "mutation",
84760
84795
  auth: "admin",
@@ -94102,6 +94137,12 @@ var require_dist_D9aw_d0G = __commonJS({
94102
94137
  addonId: null,
94103
94138
  access: "view"
94104
94139
  },
94140
+ "records.transact": {
94141
+ capName: "records",
94142
+ capScope: "system",
94143
+ addonId: null,
94144
+ access: "create"
94145
+ },
94105
94146
  "sceneMonitor.captureReference": {
94106
94147
  capName: "scene-monitor",
94107
94148
  capScope: "device",
@@ -95434,12 +95475,6 @@ var require_dist_D9aw_d0G = __commonJS({
95434
95475
  addonId: null,
95435
95476
  access: "view"
95436
95477
  },
95437
- "userManagement.listApiKeys": {
95438
- capName: "user-management",
95439
- capScope: "system",
95440
- addonId: null,
95441
- access: "view"
95442
- },
95443
95478
  "userManagement.listExternalIdentities": {
95444
95479
  capName: "user-management",
95445
95480
  capScope: "system",
@@ -95494,12 +95529,6 @@ var require_dist_D9aw_d0G = __commonJS({
95494
95529
  addonId: null,
95495
95530
  access: "create"
95496
95531
  },
95497
- "userManagement.revokeApiKey": {
95498
- capName: "user-management",
95499
- capScope: "system",
95500
- addonId: null,
95501
- access: "delete"
95502
- },
95503
95532
  "userManagement.revokeOauthSession": {
95504
95533
  capName: "user-management",
95505
95534
  capScope: "system",
@@ -99698,9 +99727,13 @@ var require_dist_D9aw_d0G = __commonJS({
99698
99727
  "stream-online": "device-events",
99699
99728
  "stream-offline": "device-events",
99700
99729
  "detection-blind": "device-events",
99730
+ "motion-noisy": "device-events",
99731
+ "motion-calm": "device-events",
99701
99732
  "recording-stalled": "device-events",
99702
99733
  "recording-healthy": "device-events",
99703
99734
  "recording-degraded": "device-events",
99735
+ "device-attention-required": "device-events",
99736
+ "device-attention-resolved": "device-events",
99704
99737
  "node-online": "system",
99705
99738
  "node-offline": "system",
99706
99739
  "node-restarting": "system",
@@ -99717,6 +99750,8 @@ var require_dist_D9aw_d0G = __commonJS({
99717
99750
  "alert-critical": "system",
99718
99751
  "alert-error": "system",
99719
99752
  "alert-critical-resolved": "system",
99753
+ "rule-broken": "system",
99754
+ "rule-repaired": "system",
99720
99755
  "storage-location-low": "system",
99721
99756
  "storage-location-critical": "system",
99722
99757
  "storage-location-ok": "system",
@@ -99781,6 +99816,12 @@ var require_dist_D9aw_d0G = __commonJS({
99781
99816
  label: "Detecting nothing",
99782
99817
  kinds: ["detection-blind"]
99783
99818
  },
99819
+ {
99820
+ id: "motion-noise",
99821
+ family: "device-events",
99822
+ label: "Motion without a subject",
99823
+ kinds: ["motion-noisy", "motion-calm"]
99824
+ },
99784
99825
  {
99785
99826
  id: "recording",
99786
99827
  family: "device-events",
@@ -99791,6 +99832,12 @@ var require_dist_D9aw_d0G = __commonJS({
99791
99832
  "recording-degraded"
99792
99833
  ]
99793
99834
  },
99835
+ {
99836
+ id: "device-attention",
99837
+ family: "device-events",
99838
+ label: "Needs attention",
99839
+ kinds: ["device-attention-required", "device-attention-resolved"]
99840
+ },
99794
99841
  {
99795
99842
  id: "nodes",
99796
99843
  family: "system",
@@ -99851,6 +99898,12 @@ var require_dist_D9aw_d0G = __commonJS({
99851
99898
  "alert-critical-resolved"
99852
99899
  ]
99853
99900
  },
99901
+ {
99902
+ id: "rule-health",
99903
+ family: "system",
99904
+ label: "Notification rules",
99905
+ kinds: ["rule-broken", "rule-repaired"]
99906
+ },
99854
99907
  {
99855
99908
  id: "alarm",
99856
99909
  family: "alarm",
@@ -99936,6 +99989,7 @@ var require_dist_D9aw_d0G = __commonJS({
99936
99989
  "alert-error",
99937
99990
  "alert-critical-resolved"
99938
99991
  ];
99992
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
99939
99993
  var UPDATES = [
99940
99994
  "addon-update-available",
99941
99995
  "server-update-available",
@@ -99965,9 +100019,12 @@ var require_dist_D9aw_d0G = __commonJS({
99965
100019
  "stream-online",
99966
100020
  "stream-offline",
99967
100021
  "detection-blind",
100022
+ "motion-noisy",
100023
+ "motion-calm",
99968
100024
  "recording-stalled",
99969
100025
  "recording-healthy",
99970
100026
  "recording-degraded",
100027
+ ...DEVICE_ATTENTION,
99971
100028
  ...ALARM
99972
100029
  ];
99973
100030
  var SUMMARISABLE = [...systemEventKindsOfFamily("device-events"), ...systemEventKindsOfFamily("system")];
@@ -100132,7 +100189,13 @@ var require_dist_D9aw_d0G = __commonJS({
100132
100189
  [...RULE_TEXT],
100133
100190
  [...RULE_TEXT],
100134
100191
  [...RULE_TEXT],
100135
- ([...RULE_TEXT], [...ALERT_EPISODE]),
100192
+ [...RULE_TEXT],
100193
+ [...RULE_TEXT],
100194
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
100195
+ [...RULE_TEXT],
100196
+ [...RULE_TEXT],
100197
+ [...RULE_TEXT],
100198
+ [...RULE_TEXT],
100136
100199
  [...RULE_TEXT],
100137
100200
  [...RULE_TEXT],
100138
100201
  [...RULE_TEXT],
@@ -100150,11 +100213,11 @@ var require_dist_D9aw_d0G = __commonJS({
100150
100213
  [...RULE_TEXT],
100151
100214
  [...RULE_TEXT],
100152
100215
  [...RULE_TEXT],
100216
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
100153
100217
  ([...RULE_TEXT], [...ALERT_EPISODE]),
100218
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
100154
100219
  ([...RULE_TEXT], [...ALERT_EPISODE]),
100155
- ([...RULE_TEXT], [...ALERT_EPISODE]),
100156
- ([...RULE_TEXT], [...ALERT_EPISODE]),
100157
- ([...RULE_TEXT], [...ALERT_EPISODE]),
100220
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
100158
100221
  [...RULE_TEXT],
100159
100222
  [...RULE_TEXT],
100160
100223
  [...RULE_TEXT],
@@ -100175,6 +100238,125 @@ var require_dist_D9aw_d0G = __commonJS({
100175
100238
  [...RULE_TEXT],
100176
100239
  ...STATE_SUMMARY_VARS
100177
100240
  ];
100241
+ new Map([
100242
+ {
100243
+ id: "device-connectivity",
100244
+ family: "device-events",
100245
+ label: "Device connectivity (offline / back online)",
100246
+ bad: ["device-offline"],
100247
+ recovery: ["device-online"],
100248
+ snapshotLabel: "Devices offline now",
100249
+ snapshotSection: "device-state"
100250
+ },
100251
+ {
100252
+ id: "device-switch",
100253
+ family: "device-events",
100254
+ label: "Device switched off / back on",
100255
+ bad: ["device-disabled"],
100256
+ recovery: ["device-enabled"],
100257
+ snapshotLabel: "Devices switched off now",
100258
+ snapshotSection: "device-state"
100259
+ },
100260
+ {
100261
+ id: "stream-connectivity",
100262
+ family: "device-events",
100263
+ label: "Stream connectivity (offline / back online)",
100264
+ bad: ["stream-offline"],
100265
+ recovery: ["stream-online"],
100266
+ snapshotLabel: "Streams offline now",
100267
+ snapshotSection: "streams"
100268
+ },
100269
+ {
100270
+ id: "battery",
100271
+ family: "device-events",
100272
+ label: "Battery (low / back to normal)",
100273
+ bad: ["device-battery-low"],
100274
+ recovery: ["device-battery-normal"],
100275
+ snapshotLabel: "Batteries low now",
100276
+ snapshotSection: "battery"
100277
+ },
100278
+ {
100279
+ id: "consumables",
100280
+ family: "device-events",
100281
+ label: "Consumables (low / replaced)",
100282
+ bad: ["device-consumable-low"],
100283
+ recovery: ["device-consumable-normal"],
100284
+ snapshotLabel: "Consumables low now",
100285
+ snapshotSection: "consumables"
100286
+ },
100287
+ {
100288
+ id: "tanks",
100289
+ family: "device-events",
100290
+ label: "Tanks (low or full / back to normal)",
100291
+ bad: ["device-tank-low", "device-tank-full"],
100292
+ recovery: ["device-tank-normal"],
100293
+ snapshotLabel: "Tanks low or full now",
100294
+ snapshotSection: "tanks"
100295
+ },
100296
+ {
100297
+ id: "motion-noise",
100298
+ family: "device-events",
100299
+ label: "Motion without a subject (constant / calm again)",
100300
+ bad: ["motion-noisy"],
100301
+ recovery: ["motion-calm"],
100302
+ snapshotLabel: "Cameras with constant motion now",
100303
+ snapshotSection: null
100304
+ },
100305
+ {
100306
+ id: "recording-health",
100307
+ family: "device-events",
100308
+ label: "Recording health (stalled or degraded / recording again)",
100309
+ bad: ["recording-stalled", "recording-degraded"],
100310
+ recovery: ["recording-healthy"],
100311
+ snapshotLabel: "Recordings stalled now",
100312
+ snapshotSection: null
100313
+ },
100314
+ {
100315
+ id: "device-attention",
100316
+ family: "device-events",
100317
+ label: "Device needs attention (raised / resolved)",
100318
+ bad: ["device-attention-required"],
100319
+ recovery: ["device-attention-resolved"],
100320
+ snapshotLabel: "Devices needing attention now",
100321
+ snapshotSection: null
100322
+ },
100323
+ {
100324
+ id: "node-connectivity",
100325
+ family: "system",
100326
+ label: "Node connectivity (offline / back online)",
100327
+ bad: ["node-offline"],
100328
+ recovery: ["node-online"],
100329
+ snapshotLabel: "Nodes offline now",
100330
+ snapshotSection: "nodes"
100331
+ },
100332
+ {
100333
+ id: "storage-space",
100334
+ family: "system",
100335
+ label: "Storage space (low or critical / ok again)",
100336
+ bad: ["storage-location-low", "storage-location-critical"],
100337
+ recovery: ["storage-location-ok"],
100338
+ snapshotLabel: "Storage locations low now",
100339
+ snapshotSection: null
100340
+ },
100341
+ {
100342
+ id: "critical-alerts",
100343
+ family: "system",
100344
+ label: "Critical alerts (raised / resolved)",
100345
+ bad: ["alert-critical"],
100346
+ recovery: ["alert-critical-resolved"],
100347
+ snapshotLabel: "Critical alerts open now",
100348
+ snapshotSection: null
100349
+ },
100350
+ {
100351
+ id: "rule-health",
100352
+ family: "system",
100353
+ label: "Rule health (broken / repaired)",
100354
+ bad: ["rule-broken"],
100355
+ recovery: ["rule-repaired"],
100356
+ snapshotLabel: "Notification rules broken now",
100357
+ snapshotSection: null
100358
+ }
100359
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
100178
100360
  var CATALOG_LANGS = AppPageLangSchema.options;
100179
100361
  var CatalogFileSchema = zod.z.record(zod.z.string().min(1), zod.z.string());
100180
100362
  function interpolate(template, params) {
@@ -100782,12 +100964,6 @@ var require_dist_D9aw_d0G = __commonJS({
100782
100964
  return AlertSchema;
100783
100965
  }
100784
100966
  });
100785
- Object.defineProperty(exports, "ApiKeyRecordSchema", {
100786
- enumerable: true,
100787
- get: function() {
100788
- return ApiKeyRecordSchema;
100789
- }
100790
- });
100791
100967
  Object.defineProperty(exports, "BaseAddon", {
100792
100968
  enumerable: true,
100793
100969
  get: function() {
@@ -101358,12 +101534,24 @@ var require_dist_D9aw_d0G = __commonJS({
101358
101534
  return StorageMigrationJobSchema;
101359
101535
  }
101360
101536
  });
101537
+ Object.defineProperty(exports, "StoredRecordKindDeclarationSchema", {
101538
+ enumerable: true,
101539
+ get: function() {
101540
+ return StoredRecordKindDeclarationSchema;
101541
+ }
101542
+ });
101361
101543
  Object.defineProperty(exports, "TokenScopeSchema", {
101362
101544
  enumerable: true,
101363
101545
  get: function() {
101364
101546
  return TokenScopeSchema;
101365
101547
  }
101366
101548
  });
101549
+ Object.defineProperty(exports, "TransactRefusedError", {
101550
+ enumerable: true,
101551
+ get: function() {
101552
+ return TransactRefusedError;
101553
+ }
101554
+ });
101367
101555
  Object.defineProperty(exports, "UNATTRIBUTED_BUCKET_KEY", {
101368
101556
  enumerable: true,
101369
101557
  get: function() {
@@ -101454,6 +101642,12 @@ var require_dist_D9aw_d0G = __commonJS({
101454
101642
  return asString$1;
101455
101643
  }
101456
101644
  });
101645
+ Object.defineProperty(exports, "assertTransactScope", {
101646
+ enumerable: true,
101647
+ get: function() {
101648
+ return assertTransactScope;
101649
+ }
101650
+ });
101457
101651
  Object.defineProperty(exports, "assertValidDeclaration", {
101458
101652
  enumerable: true,
101459
101653
  get: function() {
@@ -102519,40 +102713,6 @@ var require_dist_D9aw_d0G = __commonJS({
102519
102713
  }
102520
102714
  });
102521
102715
 
102522
- // ../system/dist/read-all-rows-CVoO1ONM.js
102523
- var require_read_all_rows_CVoO1ONM = __commonJS({
102524
- "../system/dist/read-all-rows-CVoO1ONM.js"(exports) {
102525
- "use strict";
102526
- var require_read_all_rows = /* @__PURE__ */ require_chunk_Cek0wNdY().__commonJSMin(((exports2) => {
102527
- Object.defineProperty(exports2, "__esModule", { value: true });
102528
- exports2.readAllRows = readAllRows;
102529
- var PAGE_SIZE = 1e3;
102530
- var MAX_PAGES = 100;
102531
- async function readAllRows(kind, query = {}, options = {}) {
102532
- const out = [];
102533
- let cursor;
102534
- for (let page = 0; page < MAX_PAGES; page += 1) {
102535
- const answer = await kind.query({
102536
- ...query,
102537
- limit: PAGE_SIZE,
102538
- ...cursor === void 0 ? {} : { cursor }
102539
- }, options);
102540
- out.push(...answer.records);
102541
- if (answer.nextCursor === null) return out;
102542
- cursor = answer.nextCursor;
102543
- }
102544
- throw new Error(`record kind "${kind.name}" holds more than ${MAX_PAGES * PAGE_SIZE} rows`);
102545
- }
102546
- }));
102547
- Object.defineProperty(exports, "require_read_all_rows", {
102548
- enumerable: true,
102549
- get: function() {
102550
- return require_read_all_rows;
102551
- }
102552
- });
102553
- }
102554
- });
102555
-
102556
102716
  // ../system/dist/x509.es-C4cOo48M.js
102557
102717
  var require_x509_es_C4cOo48M = __commonJS({
102558
102718
  "../system/dist/x509.es-C4cOo48M.js"(exports) {
@@ -114024,11 +114184,11 @@ ${values.join("\n")}` : `${blockName} :`;
114024
114184
  }
114025
114185
  });
114026
114186
 
114027
- // ../system/dist/device-ca-B3xUzps7.js
114028
- var require_device_ca_B3xUzps7 = __commonJS({
114029
- "../system/dist/device-ca-B3xUzps7.js"(exports) {
114187
+ // ../system/dist/device-ca-DpvQ5wrb.js
114188
+ var require_device_ca_DpvQ5wrb = __commonJS({
114189
+ "../system/dist/device-ca-DpvQ5wrb.js"(exports) {
114030
114190
  "use strict";
114031
- var require_dist10 = require_dist_D9aw_d0G();
114191
+ var require_dist10 = require_dist_QyW9hVO2();
114032
114192
  var require_x509_es = require_x509_es_C4cOo48M();
114033
114193
  var node_crypto = __require("crypto");
114034
114194
  var SYSTEM_SECRET_OWNER = "system";
@@ -114443,6 +114603,40 @@ var require_device_ca_B3xUzps7 = __commonJS({
114443
114603
  }
114444
114604
  });
114445
114605
 
114606
+ // ../system/dist/read-all-rows-CVoO1ONM.js
114607
+ var require_read_all_rows_CVoO1ONM = __commonJS({
114608
+ "../system/dist/read-all-rows-CVoO1ONM.js"(exports) {
114609
+ "use strict";
114610
+ var require_read_all_rows = /* @__PURE__ */ require_chunk_Cek0wNdY().__commonJSMin(((exports2) => {
114611
+ Object.defineProperty(exports2, "__esModule", { value: true });
114612
+ exports2.readAllRows = readAllRows;
114613
+ var PAGE_SIZE = 1e3;
114614
+ var MAX_PAGES = 100;
114615
+ async function readAllRows(kind, query = {}, options = {}) {
114616
+ const out = [];
114617
+ let cursor;
114618
+ for (let page = 0; page < MAX_PAGES; page += 1) {
114619
+ const answer = await kind.query({
114620
+ ...query,
114621
+ limit: PAGE_SIZE,
114622
+ ...cursor === void 0 ? {} : { cursor }
114623
+ }, options);
114624
+ out.push(...answer.records);
114625
+ if (answer.nextCursor === null) return out;
114626
+ cursor = answer.nextCursor;
114627
+ }
114628
+ throw new Error(`record kind "${kind.name}" holds more than ${MAX_PAGES * PAGE_SIZE} rows`);
114629
+ }
114630
+ }));
114631
+ Object.defineProperty(exports, "require_read_all_rows", {
114632
+ enumerable: true,
114633
+ get: function() {
114634
+ return require_read_all_rows;
114635
+ }
114636
+ });
114637
+ }
114638
+ });
114639
+
114446
114640
  // ../system/dist/builtins/alerts/alerts.addon.js
114447
114641
  var require_alerts_addon = __commonJS({
114448
114642
  "../system/dist/builtins/alerts/alerts.addon.js"(exports) {
@@ -114452,7 +114646,7 @@ var require_alerts_addon = __commonJS({
114452
114646
  [Symbol.toStringTag]: { value: "Module" }
114453
114647
  });
114454
114648
  require_chunk_Cek0wNdY();
114455
- var require_dist10 = require_dist_D9aw_d0G();
114649
+ var require_dist10 = require_dist_QyW9hVO2();
114456
114650
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
114457
114651
  function nextEpisodeId(input) {
114458
114652
  const { previous } = input;
@@ -114897,6 +115091,10 @@ var require_alerts_addon = __commonJS({
114897
115091
  severity: "warning",
114898
115092
  titleTemplate: "Stream offline"
114899
115093
  },
115094
+ "notification.rule-broken": {
115095
+ severity: "warning",
115096
+ titleTemplate: "Notification rule broken"
115097
+ },
114900
115098
  "backup.restored": {
114901
115099
  severity: "info",
114902
115100
  titleTemplate: "Backup restored"
@@ -114910,7 +115108,8 @@ var require_alerts_addon = __commonJS({
114910
115108
  "process.state-changed",
114911
115109
  "addon.load-recovered",
114912
115110
  "system.liveness-recovered",
114913
- "stream.online"
115111
+ "stream.online",
115112
+ "notification.rule-repaired"
114914
115113
  ];
114915
115114
  var STREAM_OUTAGE_REASONS = [
114916
115115
  "stale-timeout",
@@ -115150,6 +115349,14 @@ var require_alerts_addon = __commonJS({
115150
115349
  await this.handleStreamOnline(event);
115151
115350
  return;
115152
115351
  }
115352
+ if (category === require_dist10.EventCategory.NotificationRuleBroken) {
115353
+ await this.handleRuleBroken(event);
115354
+ return;
115355
+ }
115356
+ if (category === require_dist10.EventCategory.NotificationRuleRepaired) {
115357
+ await this.handleRuleRepaired(event);
115358
+ return;
115359
+ }
115153
115360
  const mapping = CATEGORY_MAPPINGS[category];
115154
115361
  if (!mapping) return;
115155
115362
  if (category === "addon.updated") {
@@ -115564,6 +115771,56 @@ var require_alerts_addon = __commonJS({
115564
115771
  };
115565
115772
  await this.emitAlert(alert);
115566
115773
  }
115774
+ /**
115775
+ * A notification rule that cannot work (D905) — visible in-app even when no
115776
+ * rule listens for `rule-broken`. One card per RULE; a new reason updates it.
115777
+ */
115778
+ async handleRuleBroken(event) {
115779
+ const ruleId = event.data["ruleId"];
115780
+ if (typeof ruleId !== "string" || ruleId.length === 0) return;
115781
+ const ruleName = typeof event.data["ruleName"] === "string" ? event.data["ruleName"] : ruleId;
115782
+ const reason = typeof event.data["reason"] === "string" ? event.data["reason"] : "unknown";
115783
+ const listed = event.data["offendingIds"];
115784
+ const offendingIds = Array.isArray(listed) ? listed.filter((id) => typeof id === "string") : [];
115785
+ const what = reason === "unparseable" ? "cannot be loaded and sends nothing \u2014 open it and save it again" : reason === "device-deleted" ? `still names a deleted device (${offendingIds.join(", ")}) and was switched off` : reason === "target-deleted" ? `still sends to a deleted destination (${offendingIds.join(", ")}) and was switched off` : "cannot work";
115786
+ const alert = {
115787
+ id: `nc-rule-broken:${ruleId}`,
115788
+ category: require_dist10.EventCategory.NotificationRuleBroken,
115789
+ severity: "warning",
115790
+ title: "Notification rule broken",
115791
+ message: `Rule "${ruleName}" ${what}.`,
115792
+ status: "active",
115793
+ read: false,
115794
+ createdAt: Date.now(),
115795
+ updatedAt: Date.now(),
115796
+ source: {
115797
+ type: "addon",
115798
+ id: "notification-center"
115799
+ },
115800
+ metadata: {
115801
+ ruleId,
115802
+ ruleName,
115803
+ reason,
115804
+ offendingIds,
115805
+ reasons: event.data["reasons"]
115806
+ }
115807
+ };
115808
+ await this.emitAlert(alert);
115809
+ }
115810
+ /** The rule works again — drop its broken-rule card. */
115811
+ async handleRuleRepaired(event) {
115812
+ const ruleId = event.data["ruleId"];
115813
+ if (typeof ruleId !== "string" || ruleId.length === 0) return;
115814
+ const stableId = `nc-rule-broken:${ruleId}`;
115815
+ try {
115816
+ await this.dismiss(stableId);
115817
+ } catch (err) {
115818
+ this.ctx.logger?.debug("NotificationRuleRepaired: dismiss failed (likely already dismissed)", { meta: {
115819
+ stableId,
115820
+ error: require_dist10.errMsg(err)
115821
+ } });
115822
+ }
115823
+ }
115567
115824
  /** Stream online after an outage — drop the matching offline card. */
115568
115825
  async handleStreamOnline(event) {
115569
115826
  const deviceId = event.data["deviceId"];
@@ -115857,7 +116114,7 @@ var require_calendars_addon = __commonJS({
115857
116114
  [Symbol.toStringTag]: { value: "Module" }
115858
116115
  });
115859
116116
  require_chunk_Cek0wNdY();
115860
- var require_dist10 = require_dist_D9aw_d0G();
116117
+ var require_dist10 = require_dist_QyW9hVO2();
115861
116118
  var require_settle_sources = require_settle_sources_Bhsy57y();
115862
116119
  var zod = require_zod();
115863
116120
  var CALENDAR_COLOR_PALETTE = [
@@ -116073,11 +116330,11 @@ var require_calendars = __commonJS({
116073
116330
  }
116074
116331
  });
116075
116332
 
116076
- // ../system/dist/composition-sources-oXvmbMHX.js
116077
- var require_composition_sources_oXvmbMHX = __commonJS({
116078
- "../system/dist/composition-sources-oXvmbMHX.js"(exports) {
116333
+ // ../system/dist/composition-sources-DqHwltDV.js
116334
+ var require_composition_sources_DqHwltDV = __commonJS({
116335
+ "../system/dist/composition-sources-DqHwltDV.js"(exports) {
116079
116336
  "use strict";
116080
- var require_dist10 = require_dist_D9aw_d0G();
116337
+ var require_dist10 = require_dist_QyW9hVO2();
116081
116338
  function normalizedNativeOwner(owner) {
116082
116339
  const trimmed = owner?.trim();
116083
116340
  return trimmed ? trimmed : null;
@@ -116192,8 +116449,8 @@ var require_composer_addon = __commonJS({
116192
116449
  [Symbol.toStringTag]: { value: "Module" }
116193
116450
  });
116194
116451
  require_chunk_Cek0wNdY();
116195
- var require_dist10 = require_dist_D9aw_d0G();
116196
- var require_composition_sources = require_composition_sources_oXvmbMHX();
116452
+ var require_dist10 = require_dist_QyW9hVO2();
116453
+ var require_composition_sources = require_composition_sources_DqHwltDV();
116197
116454
  var zod = require_zod();
116198
116455
  function isRecord$2(value) {
116199
116456
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -120003,7 +120260,7 @@ var require_console_logging = __commonJS({
120003
120260
  [Symbol.toStringTag]: { value: "Module" }
120004
120261
  });
120005
120262
  require_chunk_Cek0wNdY();
120006
- var require_dist10 = require_dist_D9aw_d0G();
120263
+ var require_dist10 = require_dist_QyW9hVO2();
120007
120264
  var require_formatter = require_formatter_DqAKDlvN();
120008
120265
  var LEVEL_RANK = {
120009
120266
  debug: 0,
@@ -124667,9 +124924,9 @@ var require_core_blocks_addon = __commonJS({
124667
124924
  "use strict";
124668
124925
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
124669
124926
  var require_chunk = require_chunk_Cek0wNdY();
124670
- var require_dist10 = require_dist_D9aw_d0G();
124927
+ var require_dist10 = require_dist_QyW9hVO2();
124671
124928
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
124672
- var require_composition_sources = require_composition_sources_oXvmbMHX();
124929
+ var require_composition_sources = require_composition_sources_DqHwltDV();
124673
124930
  var require_prefix_range = require_prefix_range_D_KueXbQ();
124674
124931
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
124675
124932
  var zod = require_zod();
@@ -126867,9 +127124,9 @@ var require_core_blocks = __commonJS({
126867
127124
  }
126868
127125
  });
126869
127126
 
126870
- // ../types/dist/event-category-eSqkye-K.js
126871
- var require_event_category_eSqkye_K = __commonJS({
126872
- "../types/dist/event-category-eSqkye-K.js"(exports) {
127127
+ // ../types/dist/event-category-7AwNbPjm.js
127128
+ var require_event_category_7AwNbPjm = __commonJS({
127129
+ "../types/dist/event-category-7AwNbPjm.js"(exports) {
126873
127130
  "use strict";
126874
127131
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
126875
127132
  EventCategory2["SystemBoot"] = "system.boot";
@@ -126951,6 +127208,8 @@ var require_event_category_eSqkye_K = __commonJS({
126951
127208
  EventCategory2["PipelineCameraUnassigned"] = "pipeline.camera-unassigned";
126952
127209
  EventCategory2["PipelineNodeInferenceUnavailable"] = "pipeline.node-inference-unavailable";
126953
127210
  EventCategory2["PipelineDetectionBlind"] = "pipeline.detection-blind";
127211
+ EventCategory2["PipelineMotionNoisy"] = "pipeline.motion-noisy";
127212
+ EventCategory2["PipelineMotionCalm"] = "pipeline.motion-calm";
126954
127213
  EventCategory2["PipelineCameraUpdated"] = "pipeline.camera-updated";
126955
127214
  EventCategory2["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
126956
127215
  EventCategory2["PipelineRunnerLoadSnapshot"] = "pipeline.runner-load-snapshot";
@@ -127023,6 +127282,8 @@ var require_event_category_eSqkye_K = __commonJS({
127023
127282
  EventCategory2["BackupRestored"] = "backup.restored";
127024
127283
  EventCategory2["NotificationDispatched"] = "notification.dispatched";
127025
127284
  EventCategory2["NotificationFailed"] = "notification.failed";
127285
+ EventCategory2["NotificationRuleBroken"] = "notification.rule-broken";
127286
+ EventCategory2["NotificationRuleRepaired"] = "notification.rule-repaired";
127026
127287
  EventCategory2["DeviceUpdated"] = "device.updated";
127027
127288
  EventCategory2["DeviceOnline"] = "device.online";
127028
127289
  EventCategory2["DeviceOffline"] = "device.offline";
@@ -127072,11 +127333,11 @@ var require_event_category_eSqkye_K = __commonJS({
127072
127333
  }
127073
127334
  });
127074
127335
 
127075
- // ../types/dist/sleep-Re8daN0Y.js
127076
- var require_sleep_Re8daN0Y = __commonJS({
127077
- "../types/dist/sleep-Re8daN0Y.js"(exports) {
127336
+ // ../types/dist/sleep-CD18m9HF.js
127337
+ var require_sleep_CD18m9HF = __commonJS({
127338
+ "../types/dist/sleep-CD18m9HF.js"(exports) {
127078
127339
  "use strict";
127079
- var require_event_category = require_event_category_eSqkye_K();
127340
+ var require_event_category = require_event_category_7AwNbPjm();
127080
127341
  var zod = require_zod();
127081
127342
  var AUDIO_CHUNK_FORMATS = [
127082
127343
  "f32le",
@@ -129754,7 +130015,8 @@ var require_sleep_Re8daN0Y = __commonJS({
129754
130015
  "invalid-record",
129755
130016
  "declaration-refused",
129756
130017
  "no-caller",
129757
- "batch-too-large"
130018
+ "batch-too-large",
130019
+ "transact-refused"
129758
130020
  ];
129759
130021
  var PREFIX = "records/";
129760
130022
  var RecordsError = class extends Error {
@@ -129851,6 +130113,12 @@ var require_sleep_Re8daN0Y = __commonJS({
129851
130113
  this.name = "BatchTooLargeError";
129852
130114
  }
129853
130115
  };
130116
+ var TransactRefusedError = class extends RecordsError {
130117
+ constructor(detail) {
130118
+ super("transact-refused", detail);
130119
+ this.name = "TransactRefusedError";
130120
+ }
130121
+ };
129854
130122
  var FACTORIES = {
129855
130123
  "rev-conflict": (d) => new RevConflictError(d),
129856
130124
  "too-large": (d) => new RecordTooLargeError(d),
@@ -129865,7 +130133,8 @@ var require_sleep_Re8daN0Y = __commonJS({
129865
130133
  "invalid-record": (d) => new InvalidRecordError(d),
129866
130134
  "declaration-refused": (d) => new DeclarationRefusedError(d),
129867
130135
  "no-caller": (d) => new NoCallerError(d),
129868
- "batch-too-large": (d) => new BatchTooLargeError(d)
130136
+ "batch-too-large": (d) => new BatchTooLargeError(d),
130137
+ "transact-refused": (d) => new TransactRefusedError(d)
129869
130138
  };
129870
130139
  function isCode(value) {
129871
130140
  return RECORDS_ERROR_CODES.some((code) => code === value);
@@ -130068,7 +130337,7 @@ var require_sleep_Re8daN0Y = __commonJS({
130068
130337
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
130069
130338
  fields: zod.z.record(zod.z.string(), zod.z.unknown())
130070
130339
  }).strict();
130071
- var RecordKindDeclarationSchema = zod.z.object({
130340
+ var RecordKindDeclarationShape = zod.z.object({
130072
130341
  database: zod.z.enum(RECORD_DATABASES).default("settings"),
130073
130342
  class: zod.z.enum(RECORD_CLASSES),
130074
130343
  writeTrigger: zod.z.string().min(1),
@@ -130086,18 +130355,12 @@ var require_sleep_Re8daN0Y = __commonJS({
130086
130355
  secretPaths: zod.z.array(zod.z.string().min(1)).default([]),
130087
130356
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
130088
130357
  secretArrayKeys: zod.z.record(zod.z.string(), zod.z.string()).default({}),
130089
- /**
130090
- * RETIRED (D900): the legacy table a kind adopted from during the records
130091
- * migration. Nothing declares it any more and nothing reads it; the schema
130092
- * still ACCEPTS it because the catalog rows the migration wrote carry it
130093
- * (an orphaned kind is never redeclared) and an addon built before the
130094
- * removal still sends it. Never set it.
130095
- */
130096
- adoptsFrom: zod.z.string().min(1).optional(),
130097
130358
  /** Kinds that must agree through `transact` sit in one file under one family name. */
130098
130359
  transactFamily: zod.z.string().min(1).optional(),
130099
130360
  entry: EntryDescriptorSchema.optional()
130100
- }).strict();
130361
+ });
130362
+ var RecordKindDeclarationSchema = RecordKindDeclarationShape.strict();
130363
+ var StoredRecordKindDeclarationSchema = RecordKindDeclarationShape;
130101
130364
  var RecordKindNameSchema = zod.z.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
130102
130365
  function assertValidDeclaration(name, decl) {
130103
130366
  const refuse = (why) => {
@@ -130178,6 +130441,16 @@ var require_sleep_Re8daN0Y = __commonJS({
130178
130441
  function declarationsOf(kinds) {
130179
130442
  return Object.fromEntries(Object.entries(kinds).map(([name, kind]) => [name, kind.declaration]));
130180
130443
  }
130444
+ function assertTransactScope(members) {
130445
+ const byKind = /* @__PURE__ */ new Map();
130446
+ for (const m of members) byKind.set(m.kind, m);
130447
+ const kinds = [...byKind.values()];
130448
+ if (new Set(kinds.map((m) => m.declaration.database)).size > 1) throw new TransactRefusedError(`cross-file: the ops span more than one database file (${kinds.map((m) => `${m.kind}@${m.declaration.database}`).join(", ")}); a transaction lives in ONE file`);
130449
+ if (kinds.length <= 1) return;
130450
+ const missing = kinds.filter((m) => m.declaration.transactFamily === void 0);
130451
+ if (missing.length > 0) throw new TransactRefusedError(`no-family: ${missing.map((m) => m.kind).join(", ")} declare no transactFamily; kinds that must agree through transact share one`);
130452
+ if (new Set(kinds.map((m) => m.declaration.transactFamily)).size > 1) throw new TransactRefusedError(`cross-family: the ops span more than one transactFamily (${kinds.map((m) => `${m.kind}=${String(m.declaration.transactFamily)}`).join(", ")})`);
130453
+ }
130181
130454
  function isRecord$2(value) {
130182
130455
  return typeof value === "object" && value !== null && !Array.isArray(value);
130183
130456
  }
@@ -130351,6 +130624,48 @@ var require_sleep_Re8daN0Y = __commonJS({
130351
130624
  };
130352
130625
  });
130353
130626
  }
130627
+ async txPut(input, opts = {}) {
130628
+ const checked = this.validate(input.data, input.id);
130629
+ const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
130630
+ return {
130631
+ wire: {
130632
+ op: "put",
130633
+ kind: this.name,
130634
+ record: {
130635
+ ...input,
130636
+ data: toBody(body)
130637
+ },
130638
+ ...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
130639
+ },
130640
+ rollback
130641
+ };
130642
+ }
130643
+ async txPatch(id, partial, opts = {}) {
130644
+ const { body, rollback } = await this.storeSecrets(id, partial, "patch");
130645
+ return {
130646
+ wire: {
130647
+ op: "patch",
130648
+ kind: this.name,
130649
+ id,
130650
+ data: toBody(body),
130651
+ ...opts.at === void 0 ? {} : { at: opts.at },
130652
+ ...opts.expiresAt === void 0 ? {} : { expiresAt: opts.expiresAt },
130653
+ ...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
130654
+ },
130655
+ rollback
130656
+ };
130657
+ }
130658
+ txDelete(id) {
130659
+ return {
130660
+ wire: {
130661
+ op: "delete",
130662
+ kind: this.name,
130663
+ id
130664
+ },
130665
+ rollback: async () => {
130666
+ }
130667
+ };
130668
+ }
130354
130669
  async put(input, opts = {}) {
130355
130670
  const checked = this.validate(input.data, input.id);
130356
130671
  const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
@@ -130504,6 +130819,23 @@ var require_sleep_Re8daN0Y = __commonJS({
130504
130819
  handles.set(definition, handle);
130505
130820
  return handle;
130506
130821
  },
130822
+ async transact(ops) {
130823
+ if (ops.length === 0) return [];
130824
+ const result = await call(() => options.transport.transact({ ops: ops.map((op) => op.wire) })).catch(async (err) => {
130825
+ for (const op of ops) await op.rollback();
130826
+ throw err;
130827
+ });
130828
+ const released = [...result.releasedRefs, ...result.secretRefs];
130829
+ if (released.length > 0 && options.secrets !== null) try {
130830
+ await options.secrets.delete(released);
130831
+ } catch (err) {
130832
+ options.logger?.warn("records: could not remove released keychain values", { meta: {
130833
+ count: released.length,
130834
+ error: err instanceof Error ? err.message : "unknown"
130835
+ } });
130836
+ }
130837
+ return result.results;
130838
+ },
130507
130839
  async deleteDevice(deviceId, opts = {}) {
130508
130840
  const result = await call(() => options.transport.deleteDevice({
130509
130841
  deviceId,
@@ -130995,312 +131327,372 @@ var require_sleep_Re8daN0Y = __commonJS({
130995
131327
  secretRefs: refsOf(decl, gone)
130996
131328
  };
130997
131329
  };
130998
- return {
130999
- records: createRecordsAccess({
131000
- owner,
131001
- transport: {
131002
- declareKinds: async ({ kinds }) => {
131003
- const out = {};
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";
131013
- decls.set(name, decl);
131014
- out[name] = {
131015
- kindId,
131016
- state,
131017
- createdIndexes: created,
131018
- adoptionPending: null
131019
- };
131020
- }
131021
- return { kinds: out };
131022
- },
131023
- get: async ({ kind, id }) => {
131024
- reading();
131025
- const decl = declOf(kind);
131026
- const row = table(kind).get(id);
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
- });
131036
- },
131037
- secretRefs: async ({ kind, ids }) => {
131038
- reading();
131039
- const decl = declOf(kind);
131040
- const out = {};
131041
- for (const id of ids) {
131042
- const row = table(kind).get(id);
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;
131046
- }
131047
- return out;
131048
- },
131049
- put: async ({ kind, record, ifRev }) => {
131050
- writing();
131051
- const written = writeRecord(kind, record, ifRev, now());
131052
- afterWrite(kind, [record.deviceId]);
131053
- return {
131054
- rev: written.rev,
131055
- releasedRefs: [...written.released]
131056
- };
131057
- },
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;
131067
- const 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;
131330
+ const transport = {
131331
+ declareKinds: async ({ kinds }) => {
131332
+ const out = {};
131333
+ for (const [name, raw] of Object.entries(kinds)) {
131334
+ const decl = RecordKindDeclarationSchema.parse(raw);
131335
+ assertValidDeclaration(name, decl);
131336
+ const prior = decls.get(name);
131337
+ if (prior !== void 0) assertAdditive(name, prior, decl);
131338
+ const kindId = kindIds.get(name) ?? kindIds.size + 1;
131339
+ kindIds.set(name, kindId);
131340
+ const created = decl.indexes.filter((i) => prior?.indexes.every((p) => p.name !== i.name) ?? true).map((i) => i.name);
131341
+ const state = prior === void 0 ? "created" : JSON.stringify(prior) === JSON.stringify(decl) ? "unchanged" : "updated";
131342
+ decls.set(name, decl);
131343
+ out[name] = {
131344
+ kindId,
131345
+ state,
131346
+ createdIndexes: created
131347
+ };
131348
+ }
131349
+ return { kinds: out };
131350
+ },
131351
+ get: async ({ kind, id }) => {
131352
+ reading();
131353
+ const decl = declOf(kind);
131354
+ const row = table(kind).get(id);
131355
+ return row === void 0 ? null : view(decl, row);
131356
+ },
131357
+ getMany: async ({ kind, ids }) => {
131358
+ reading();
131359
+ const decl = declOf(kind);
131360
+ return [...new Set(ids)].sort((a, b) => compareSql(a, b)).flatMap((id) => {
131361
+ const row = table(kind).get(id);
131362
+ return row === void 0 ? [] : [view(decl, row)];
131363
+ });
131364
+ },
131365
+ secretRefs: async ({ kind, ids }) => {
131366
+ reading();
131367
+ const decl = declOf(kind);
131368
+ const out = {};
131369
+ for (const id of ids) {
131370
+ const row = table(kind).get(id);
131371
+ if (row === void 0) continue;
131372
+ const refs = Object.fromEntries(markersOf(decl, row.data));
131373
+ if (Object.keys(refs).length > 0) out[id] = refs;
131374
+ }
131375
+ return out;
131376
+ },
131377
+ put: async ({ kind, record, ifRev }) => {
131378
+ writing();
131379
+ const written = writeRecord(kind, record, ifRev, now());
131380
+ afterWrite(kind, [record.deviceId]);
131381
+ return {
131382
+ rev: written.rev,
131383
+ releasedRefs: [...written.released]
131384
+ };
131385
+ },
131386
+ putMany: async ({ kind, records }) => {
131387
+ writing();
131388
+ declOf(kind);
131389
+ if (records.length > 1e3) throw new BatchTooLargeError(`${records.length} records exceed ${RECORD_BATCH_MAX}`);
131390
+ const bytes = records.reduce((sum, r) => sum + Buffer.byteLength(JSON.stringify(r.data), "utf8"), 0);
131391
+ if (bytes > 4194304) throw new BatchTooLargeError(`${bytes} bytes exceed ${RECORD_BATCH_MAX_BYTES}`);
131392
+ const nowMs = now();
131393
+ const before = new Map(table(kind));
131394
+ const ridBefore = nextRid;
131395
+ const released = [];
131396
+ try {
131397
+ for (const rec of records) released.push(...writeRecord(kind, rec, void 0, nowMs).released);
131398
+ } catch (err) {
131399
+ tables.set(kind, before);
131400
+ nextRid = ridBefore;
131401
+ throw err;
131402
+ }
131403
+ let top = -1;
131404
+ for (const r of records) if (/^\d{1,15}$/.test(r.id)) top = Math.max(top, Number(r.id));
131405
+ if (top >= 0) sequences.set(kind, Math.max(sequences.get(kind) ?? 0, top + 1));
131406
+ afterWrite(kind, records.map((r) => r.deviceId));
131407
+ return {
131408
+ count: records.length,
131409
+ releasedRefs: released
131410
+ };
131411
+ },
131412
+ patch: async (input) => {
131413
+ writing();
131414
+ const decl = declOf(input.kind);
131415
+ if (input.at !== void 0 && decl.at !== "required") throw new InvalidRecordError(`${input.kind}: declared at: "none"`);
131416
+ if (input.at === null) throw new InvalidRecordError(`${input.kind}: "at" cannot be removed`);
131417
+ 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)`);
131418
+ if (input.expiresAt !== void 0 && "ttlMs" in decl.retention) throw new InvalidRecordError(`${input.kind}: expiresAt is set by the engine`);
131419
+ const before = table(input.kind).get(input.id);
131420
+ const checked = enforceSecrets(owner, input.kind, decl, input.id, input.data, before?.data ?? null, "patch");
131421
+ if (before === void 0) throw new RecordNotFoundError(`${input.kind}/${input.id}: no such row`);
131422
+ 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}`);
131423
+ const merged = jsonCopy(mergePatch(before.data, jsonCopy(checked.body)));
131424
+ const size = [...JSON.stringify(merged)].length;
131425
+ if (size > decl.maxDataBytes) throw new RecordTooLargeError(`${input.kind}/${input.id}: the patched body is ${size} bytes, over maxDataBytes ${decl.maxDataBytes}`);
131426
+ assertUnique(input.kind, decl, input.id, merged);
131427
+ const rev = before.rev + 1;
131428
+ store2(input.kind, before, {
131429
+ ...before,
131430
+ at: input.at ?? before.at,
131431
+ expiresAt: input.expiresAt === void 0 ? before.expiresAt : input.expiresAt,
131432
+ rev,
131433
+ updatedAt: now(),
131434
+ data: merged
131435
+ });
131436
+ const kept = new Set(markersOf(decl, merged).values());
131437
+ return {
131438
+ rev,
131439
+ releasedRefs: [...markersOf(decl, before.data).values()].filter((r) => !kept.has(r))
131440
+ };
131441
+ },
131442
+ delete: async ({ kind, id }) => {
131443
+ writing();
131444
+ const decl = declOf(kind);
131445
+ const row = table(kind).get(id);
131446
+ if (row === void 0) return {
131447
+ deleted: false,
131448
+ secretRefs: []
131449
+ };
131450
+ table(kind).delete(id);
131451
+ return {
131452
+ deleted: true,
131453
+ secretRefs: refsOf(decl, [row])
131454
+ };
131455
+ },
131456
+ deleteMany: async ({ kind, ids }) => {
131457
+ writing();
131458
+ const wanted = new Set(ids);
131459
+ return removeWhere(kind, (row) => wanted.has(row.id));
131460
+ },
131461
+ query: async (q) => {
131462
+ reading();
131463
+ const decl = declOf(q.kind);
131464
+ queries.push({
131465
+ kind: q.kind,
131466
+ limit: q.limit
131467
+ });
131468
+ assertWindowAllowed(q.kind, decl, q);
131469
+ const desc = q.desc === true;
131470
+ const dir = desc ? "DESC" : "ASC";
131471
+ const where = planWhere(q.kind, decl, q.where, { allowIn: false });
131472
+ const cursor = q.cursor === void 0 ? void 0 : decodeCursor(q.cursor);
131473
+ let rows = [...table(q.kind).values()].filter((r) => inWindow(r, q));
131474
+ let keysOf;
131475
+ let keyCount;
131476
+ let tag;
131477
+ if (where !== null) {
131478
+ if (q.order !== void 0) throw new InvalidRecordError(`${q.kind}: with a where the order is the index's; drop "order"`);
131479
+ const fields = where.orderFields;
131480
+ keysOf = (row) => [...fields.map((f) => extractField(row.data, f)), row.rid];
131481
+ keyCount = fields.length;
131482
+ tag = `rx:${where.indexName}:${dir}`;
131483
+ rows = rows.filter((r) => where.matches(r.data));
131484
+ if (cursor !== void 0) {
131485
+ assertCursor(cursor, tag, fields.length + 1);
131486
+ rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
131487
+ }
131488
+ } else {
131489
+ const order = q.order ?? (decl.at === "required" ? "at" : "id");
131490
+ keyCount = 1;
131491
+ if (order === "at") {
131492
+ if (decl.at !== "required") throw new InvalidRecordError(`${q.kind}: declared at: "none", it has no time order - use order: "id"`);
131493
+ keysOf = (row) => [row.at, row.rid];
131494
+ tag = `at:${dir}`;
131495
+ if (cursor !== void 0) {
131496
+ assertCursor(cursor, tag, 2);
131497
+ rows = rows.filter((r) => rowValueAfter(keysOf(r), cursor.values, desc));
131074
131498
  }
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));
131079
- return {
131080
- count: records.length,
131081
- releasedRefs: released
131082
- };
131083
- },
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
131499
+ } else {
131500
+ 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")`);
131501
+ keysOf = (row) => [row.id, row.rid];
131502
+ tag = `id:${dir}`;
131503
+ if (cursor !== void 0) {
131504
+ assertCursor(cursor, tag, 2);
131505
+ const last2 = cursor.values[0] ?? null;
131506
+ rows = rows.filter((r) => rowValueAfter([r.id], [last2], desc));
131507
+ }
131508
+ }
131509
+ }
131510
+ rows.sort((a, b) => (desc ? -1 : 1) * compareKeys(keysOf(a), keysOf(b)));
131511
+ const page = rows.slice(0, q.limit);
131512
+ const more = rows.length > q.limit;
131513
+ const last = page.at(-1);
131514
+ let nextCursor = null;
131515
+ if (more && last !== void 0) {
131516
+ const all = keysOf(last);
131517
+ const keys = [];
131518
+ for (let i = 0; i < keyCount; i += 1) {
131519
+ const value = all[i];
131520
+ 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`);
131521
+ keys.push(value);
131522
+ }
131523
+ keys.push(last.rid);
131524
+ nextCursor = encodeCursor(tag, keys);
131525
+ }
131526
+ return {
131527
+ records: page.map((r) => view(decl, r)),
131528
+ nextCursor
131529
+ };
131530
+ },
131531
+ count: async (q) => {
131532
+ reading();
131533
+ const decl = declOf(q.kind);
131534
+ assertWindowAllowed(q.kind, decl, q);
131535
+ const where = planWhere(q.kind, decl, q.where, { allowIn: true });
131536
+ let n = 0;
131537
+ for (const row of table(q.kind).values()) if (inWindow(row, q) && (where === null || where.matches(row.data))) n += 1;
131538
+ return { count: n };
131539
+ },
131540
+ histogram: async (q) => {
131541
+ reading();
131542
+ const decl = declOf(q.kind);
131543
+ assertWindowAllowed(q.kind, decl, {
131544
+ deviceId: q.deviceId,
131545
+ atFrom: q.from
131546
+ });
131547
+ if (!(q.to > q.from)) throw new InvalidRecordError(`${q.kind}: histogram needs from < to`);
131548
+ if (Math.ceil((q.to - q.from) / q.bucketMs) > 1e4) throw new InvalidRecordError(`${q.kind}: histogram would exceed ${HISTOGRAM_MAX_BUCKETS} buckets`);
131549
+ const from = Math.floor(q.from);
131550
+ const to = Math.ceil(q.to);
131551
+ const step = Math.trunc(q.bucketMs);
131552
+ const counts = /* @__PURE__ */ new Map();
131553
+ for (const row of table(q.kind).values()) {
131554
+ if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) continue;
131555
+ if (row.at === null || row.at < from || row.at >= to) continue;
131556
+ const b = Math.trunc((row.at - from) / step);
131557
+ counts.set(b, (counts.get(b) ?? 0) + 1);
131558
+ }
131559
+ return { buckets: [...counts.entries()].sort(([a], [b]) => a - b).map(([b, count]) => ({
131560
+ bucketStart: from + b * q.bucketMs,
131561
+ count
131562
+ })) };
131563
+ },
131564
+ aggregate: async (q) => {
131565
+ reading();
131566
+ const decl = declOf(q.kind);
131567
+ if (q.op !== "count" && q.field === void 0) throw new InvalidRecordError(`${q.kind}: ${q.op} needs a field`);
131568
+ const extra = [q.field, q.groupBy].filter((f) => f !== void 0);
131569
+ if (extra.length === 0 && q.where === void 0) throw new InvalidRecordError(`${q.kind}: a count with no field and no groupBy is "count"`);
131570
+ const where = planWhere(q.kind, decl, q.where, {
131571
+ allowIn: true,
131572
+ extraFields: extra,
131573
+ groupBy: q.groupBy
131574
+ });
131575
+ if (where === null) throw new InvalidRecordError(`${q.kind}: aggregate has nothing to read`);
131576
+ const rows = [...table(q.kind).values()].filter((r) => where.matches(r.data));
131577
+ const groups = /* @__PURE__ */ new Map();
131578
+ if (q.groupBy === void 0) groups.set(null, rows);
131579
+ else {
131580
+ const by = q.groupBy;
131581
+ for (const row of rows) {
131582
+ const g = extractField(row.data, by);
131583
+ groups.set(g, [...groups.get(g) ?? [], row]);
131584
+ }
131585
+ }
131586
+ return { rows: [...groups.entries()].sort(([a], [b]) => compareSql(a, b)).map(([group, members]) => ({
131587
+ group,
131588
+ value: aggregateOf(q.op, q.field, members)
131589
+ })) };
131590
+ },
131591
+ deleteWhere: async (q) => {
131592
+ writing();
131593
+ const decl = declOf(q.kind);
131594
+ 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"`);
131595
+ assertWindowAllowed(q.kind, decl, {
131596
+ deviceId: q.deviceId,
131597
+ atFrom: q.atBefore
131598
+ });
131599
+ const where = planWhere(q.kind, decl, q.where, { allowIn: true });
131600
+ return removeWhere(q.kind, (row) => {
131601
+ if (where !== null && !where.matches(row.data)) return false;
131602
+ if (q.deviceId !== void 0 && row.deviceId !== q.deviceId) return false;
131603
+ if (q.atBefore !== void 0 && (row.at === null || row.at >= q.atBefore)) return false;
131604
+ return true;
131605
+ });
131606
+ },
131607
+ transact: async ({ ops }) => {
131608
+ writing();
131609
+ assertTransactScope(ops.map((op) => ({
131610
+ kind: op.kind,
131611
+ declaration: declOf(op.kind)
131612
+ })));
131613
+ const before = new Map([...tables].map(([name, rows]) => [name, new Map(rows)]));
131614
+ const ridBefore = nextRid;
131615
+ const results = [];
131616
+ const releasedRefs = [];
131617
+ const secretRefs = [];
131618
+ try {
131619
+ for (const op of ops) if (op.op === "put") {
131620
+ const r = await transport.put({
131621
+ kind: op.kind,
131622
+ record: op.record,
131623
+ ...op.ifRev === void 0 ? {} : { ifRev: op.ifRev }
131107
131624
  });
131108
- const kept = new Set(markersOf(decl, merged).values());
131109
- return {
131110
- rev,
131111
- releasedRefs: [...markersOf(decl, before.data).values()].filter((r) => !kept.has(r))
131112
- };
131113
- },
131114
- delete: async ({ kind, id }) => {
131115
- writing();
131116
- const decl = declOf(kind);
131117
- const row = table(kind).get(id);
131118
- if (row === void 0) return {
131119
- deleted: false,
131120
- secretRefs: []
131121
- };
131122
- table(kind).delete(id);
131123
- return {
131124
- deleted: true,
131125
- secretRefs: refsOf(decl, [row])
131126
- };
131127
- },
131128
- deleteMany: async ({ kind, ids }) => {
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
131625
+ releasedRefs.push(...r.releasedRefs);
131626
+ results.push({
131627
+ rev: r.rev,
131628
+ deleted: false
131139
131629
  });
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);
131197
- }
131198
- return {
131199
- records: page.map((r) => view(decl, r)),
131200
- nextCursor
131201
- };
131202
- },
131203
- count: async (q) => {
131204
- reading();
131205
- const decl = declOf(q.kind);
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
131630
+ } else if (op.op === "patch") {
131631
+ const r = await transport.patch({
131632
+ kind: op.kind,
131633
+ id: op.id,
131634
+ data: op.data,
131635
+ ...op.at === void 0 ? {} : { at: op.at },
131636
+ ...op.expiresAt === void 0 ? {} : { expiresAt: op.expiresAt },
131637
+ ...op.ifRev === void 0 ? {} : { ifRev: op.ifRev }
131218
131638
  });
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
131639
+ releasedRefs.push(...r.releasedRefs);
131640
+ results.push({
131641
+ rev: r.rev,
131642
+ deleted: false
131246
131643
  });
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
131644
+ } else {
131645
+ const r = await transport.delete({
131646
+ kind: op.kind,
131647
+ id: op.id
131270
131648
  });
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;
131649
+ secretRefs.push(...r.secretRefs);
131650
+ results.push({
131651
+ rev: null,
131652
+ deleted: r.deleted
131277
131653
  });
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
- }
131290
- return {
131291
- deleted,
131292
- secretRefs
131293
- };
131294
- },
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
131654
  }
131303
- },
131655
+ } catch (err) {
131656
+ tables.clear();
131657
+ for (const [name, rows] of before) tables.set(name, rows);
131658
+ nextRid = ridBefore;
131659
+ throw err;
131660
+ }
131661
+ return {
131662
+ results,
131663
+ releasedRefs,
131664
+ secretRefs
131665
+ };
131666
+ },
131667
+ deleteDevice: async ({ deviceId, kinds }) => {
131668
+ writing();
131669
+ const deleted = {};
131670
+ const secretRefs = [];
131671
+ for (const [kind, decl] of decls) {
131672
+ if (decl.deviceRemoval !== "delete") continue;
131673
+ if (kinds !== void 0 && !kinds.includes(kind)) continue;
131674
+ const result = removeWhere(kind, (row) => row.deviceId === deviceId);
131675
+ deleted[kind] = result.deleted;
131676
+ secretRefs.push(...result.secretRefs);
131677
+ }
131678
+ return {
131679
+ deleted,
131680
+ secretRefs
131681
+ };
131682
+ },
131683
+ allocateId: async ({ kind }) => {
131684
+ writing();
131685
+ declOf(kind);
131686
+ const id = sequences.get(kind) ?? 1;
131687
+ sequences.set(kind, id + 1);
131688
+ pendingAllocated.add(`${kind}:${id}`);
131689
+ return { id };
131690
+ }
131691
+ };
131692
+ return {
131693
+ records: createRecordsAccess({
131694
+ owner,
131695
+ transport,
131304
131696
  secrets: makeSpecKeychain(owner).access
131305
131697
  }),
131306
131698
  tables,
@@ -134325,6 +134717,12 @@ var require_sleep_Re8daN0Y = __commonJS({
134325
134717
  return SHARE_VIEW_KINDS;
134326
134718
  }
134327
134719
  });
134720
+ Object.defineProperty(exports, "StoredRecordKindDeclarationSchema", {
134721
+ enumerable: true,
134722
+ get: function() {
134723
+ return StoredRecordKindDeclarationSchema;
134724
+ }
134725
+ });
134328
134726
  Object.defineProperty(exports, "StreamSourceEntrySchema", {
134329
134727
  enumerable: true,
134330
134728
  get: function() {
@@ -134349,6 +134747,12 @@ var require_sleep_Re8daN0Y = __commonJS({
134349
134747
  return SubscribeAudioChunksResultSchema;
134350
134748
  }
134351
134749
  });
134750
+ Object.defineProperty(exports, "TransactRefusedError", {
134751
+ enumerable: true,
134752
+ get: function() {
134753
+ return TransactRefusedError;
134754
+ }
134755
+ });
134352
134756
  Object.defineProperty(exports, "UnindexedFilterError", {
134353
134757
  enumerable: true,
134354
134758
  get: function() {
@@ -134427,6 +134831,12 @@ var require_sleep_Re8daN0Y = __commonJS({
134427
134831
  return asString;
134428
134832
  }
134429
134833
  });
134834
+ Object.defineProperty(exports, "assertTransactScope", {
134835
+ enumerable: true,
134836
+ get: function() {
134837
+ return assertTransactScope;
134838
+ }
134839
+ });
134430
134840
  Object.defineProperty(exports, "assertValidDeclaration", {
134431
134841
  enumerable: true,
134432
134842
  get: function() {
@@ -135083,8 +135493,8 @@ var require_addon = __commonJS({
135083
135493
  "../types/dist/addon.js"(exports) {
135084
135494
  "use strict";
135085
135495
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
135086
- var require_sleep = require_sleep_Re8daN0Y();
135087
- var require_event_category = require_event_category_eSqkye_K();
135496
+ var require_sleep = require_sleep_CD18m9HF();
135497
+ var require_event_category = require_event_category_7AwNbPjm();
135088
135498
  var require_err_msg = require_err_msg_BhVbr0NX();
135089
135499
  var CAP_INPUT_DEFAULTS = Object.freeze({
135090
135500
  "addons": { "getLogs": { "limit": 100 } },
@@ -136100,6 +136510,18 @@ var require_addon = __commonJS({
136100
136510
  "empty"
136101
136511
  ]
136102
136512
  },
136513
+ {
136514
+ "path": "filterCleaningDue",
136515
+ "valueType": "boolean"
136516
+ },
136517
+ {
136518
+ "path": "machineCareDue",
136519
+ "valueType": "boolean"
136520
+ },
136521
+ {
136522
+ "path": "machineCareRemainingRuns",
136523
+ "valueType": "number"
136524
+ },
136103
136525
  {
136104
136526
  "path": "halfLoad",
136105
136527
  "valueType": "boolean"
@@ -137361,6 +137783,8 @@ var require_addon = __commonJS({
137361
137783
  exports.RevConflictError = require_sleep.RevConflictError;
137362
137784
  exports.SECRET_CLEAR = require_sleep.SECRET_CLEAR;
137363
137785
  exports.SECRET_REF_SCHEME = require_sleep.SECRET_REF_SCHEME;
137786
+ exports.StoredRecordKindDeclarationSchema = require_sleep.StoredRecordKindDeclarationSchema;
137787
+ exports.TransactRefusedError = require_sleep.TransactRefusedError;
137364
137788
  exports.UnindexedFilterError = require_sleep.UnindexedFilterError;
137365
137789
  exports.UnknownRecordKindError = require_sleep.UnknownRecordKindError;
137366
137790
  exports.addonSliceHandleApi = require_sleep.addonSliceHandleApi;
@@ -137369,6 +137793,7 @@ var require_addon = __commonJS({
137369
137793
  exports.asJsonObject = require_sleep.asJsonObject;
137370
137794
  exports.asRecordsError = require_sleep.asRecordsError;
137371
137795
  exports.asString = require_sleep.asString;
137796
+ exports.assertTransactScope = require_sleep.assertTransactScope;
137372
137797
  exports.assertValidDeclaration = require_sleep.assertValidDeclaration;
137373
137798
  exports.buildSecretRef = require_sleep.buildSecretRef;
137374
137799
  exports.classifySecretWrite = require_sleep.classifySecretWrite;
@@ -137726,7 +138151,7 @@ var require_device_manager_addon = __commonJS({
137726
138151
  [Symbol.toStringTag]: { value: "Module" }
137727
138152
  });
137728
138153
  require_chunk_Cek0wNdY();
137729
- var require_dist10 = require_dist_D9aw_d0G();
138154
+ var require_dist10 = require_dist_QyW9hVO2();
137730
138155
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
137731
138156
  var require_prefix_range = require_prefix_range_D_KueXbQ();
137732
138157
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
@@ -146798,7 +147223,7 @@ var require_hub_forwarder = __commonJS({
146798
147223
  [Symbol.toStringTag]: { value: "Module" }
146799
147224
  });
146800
147225
  require_chunk_Cek0wNdY();
146801
- var require_dist10 = require_dist_D9aw_d0G();
147226
+ var require_dist10 = require_dist_QyW9hVO2();
146802
147227
  var require_formatter = require_formatter_DqAKDlvN();
146803
147228
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
146804
147229
  var HubForwarderDestination = class {
@@ -146932,7 +147357,7 @@ var require_liveness_monitor_addon = __commonJS({
146932
147357
  "use strict";
146933
147358
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
146934
147359
  require_chunk_Cek0wNdY();
146935
- var require_dist10 = require_dist_D9aw_d0G();
147360
+ var require_dist10 = require_dist_QyW9hVO2();
146936
147361
  var NO_DEVICES = "liveness:no-devices";
146937
147362
  var ALL_OFFLINE = "liveness:all-devices-offline";
146938
147363
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -147295,11 +147720,11 @@ var require_local_auth_addon = __commonJS({
147295
147720
  [Symbol.toStringTag]: { value: "Module" }
147296
147721
  });
147297
147722
  var require_chunk = require_chunk_Cek0wNdY();
147298
- var require_dist10 = require_dist_D9aw_d0G();
147299
- var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
147723
+ var require_dist10 = require_dist_QyW9hVO2();
147300
147724
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
147301
147725
  var require_ms$1 = require_ms_LB3giGoU();
147302
- var require_device_ca = require_device_ca_B3xUzps7();
147726
+ var require_device_ca = require_device_ca_DpvQ5wrb();
147727
+ var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
147303
147728
  var zod = require_zod();
147304
147729
  var node_crypto = __require("crypto");
147305
147730
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -147309,75 +147734,6 @@ var require_local_auth_addon = __commonJS({
147309
147734
  node_path = require_chunk.__toESM(node_path);
147310
147735
  var node_fs = __require("fs");
147311
147736
  node_fs = require_chunk.__toESM(node_fs);
147312
- function parseRecord$2(kind, schema, data) {
147313
- try {
147314
- return schema.parse(data);
147315
- } catch (err) {
147316
- const topKeys = data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).join(", ") || "(empty)" : `(non-object: ${typeof data})`;
147317
- const detail = err instanceof Error ? err.message : String(err);
147318
- const hint = data && typeof data === "object" && !Array.isArray(data) && Object.keys(data).length === 1 && "data" in data ? " This shape is the legacy double-wrap from a stale settings-store query path. Restart the server with the latest @camstack/system build." : "";
147319
- throw new Error(`Failed to parse ${kind} from settings store. Top-level keys=[${topKeys}].${hint} Underlying: ${detail}`, { cause: err });
147320
- }
147321
- }
147322
- var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
147323
- var API_KEYS_COLLECTION$1 = "api_keys";
147324
- function parseApiKey(data) {
147325
- return parseRecord$2("api-key", require_dist10.ApiKeyRecordSchema, data);
147326
- }
147327
- function rowToApiKey(id, body) {
147328
- return parseApiKey({
147329
- id,
147330
- ...body
147331
- });
147332
- }
147333
- var ApiKeyManager = class {
147334
- kind;
147335
- legacyStore;
147336
- constructor(deps) {
147337
- if ("apiKeysKind" in deps) {
147338
- this.kind = deps.apiKeysKind;
147339
- this.legacyStore = deps.legacyStore ?? null;
147340
- } else {
147341
- this.kind = null;
147342
- this.legacyStore = deps.getStore();
147343
- }
147344
- }
147345
- get store() {
147346
- if (this.legacyStore === null) throw new Error("ApiKeyManager: legacy store unavailable on records-only path");
147347
- return this.legacyStore;
147348
- }
147349
- async listAll() {
147350
- const kind = this.kind;
147351
- return (kind !== null ? (await (0, import_read_all_rows.readAllRows)(kind)).map((row) => rowToApiKey(row.id, row.data)) : (await this.store.query.query({ collection: API_KEYS_COLLECTION$1 })).map((r2) => parseApiKey(r2.data))).map((parsed) => {
147352
- const { tokenHash: _th, ...rest } = parsed;
147353
- return rest;
147354
- });
147355
- }
147356
- async revoke(id) {
147357
- const kind = this.kind;
147358
- if (kind !== null) {
147359
- await kind.delete(id);
147360
- return;
147361
- }
147362
- await this.store.delete.mutate({
147363
- collection: API_KEYS_COLLECTION$1,
147364
- key: id
147365
- });
147366
- }
147367
- async findById(id) {
147368
- const kind = this.kind;
147369
- if (kind !== null) {
147370
- const row = await kind.get(id);
147371
- return row === null ? null : rowToApiKey(row.id, row.data);
147372
- }
147373
- const results = await this.store.query.query({
147374
- collection: API_KEYS_COLLECTION$1,
147375
- filter: { where: { id } }
147376
- });
147377
- if (results.length === 0) return null;
147378
- return parseApiKey(results[0].data);
147379
- }
147380
- };
147381
147737
  var randomFallback = null;
147382
147738
  function randomBytes$1(len) {
147383
147739
  try {
@@ -152082,6 +152438,7 @@ var require_local_auth_addon = __commonJS({
152082
152438
  }
152083
152439
  }
152084
152440
  };
152441
+ var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
152085
152442
  var AUTH_AUDIT_COLLECTION = "auth_audit";
152086
152443
  var AUTH_AUDIT_COLUMNS = [
152087
152444
  {
@@ -152130,7 +152487,7 @@ var require_local_auth_addon = __commonJS({
152130
152487
  ];
152131
152488
  var RETENTION_MS = 90 * 864e5;
152132
152489
  var MAX_LIST = 500;
152133
- function parseRecord$1(data) {
152490
+ function parseRecord$2(data) {
152134
152491
  const id = data["id"];
152135
152492
  const rawAt = data["at"];
152136
152493
  const at = typeof rawAt === "number" ? rawAt : typeof rawAt === "string" && rawAt.trim() !== "" && Number.isFinite(Number(rawAt)) ? Number(rawAt) : null;
@@ -152223,7 +152580,7 @@ var require_local_auth_addon = __commonJS({
152223
152580
  order: "at",
152224
152581
  desc: true,
152225
152582
  limit
152226
- })).records.map((row) => parseRecord$1({
152583
+ })).records.map((row) => parseRecord$2({
152227
152584
  id: row.id,
152228
152585
  at: row.at,
152229
152586
  action: row.data.action,
@@ -152234,7 +152591,7 @@ var require_local_auth_addon = __commonJS({
152234
152591
  return (await this.store.query.query({
152235
152592
  collection: AUTH_AUDIT_COLLECTION,
152236
152593
  ...input.userId !== void 0 ? { filter: { where: { userId: input.userId } } } : {}
152237
- })).map((row) => parseRecord$1(row.data)).filter((r2) => r2 !== null).toSorted((a2, b) => b.at - a2.at).slice(0, limit);
152594
+ })).map((row) => parseRecord$2(row.data)).filter((r2) => r2 !== null).toSorted((a2, b) => b.at - a2.at).slice(0, limit);
152238
152595
  }
152239
152596
  /** Delete rows older than 90 days. Returns how many. */
152240
152597
  async reap() {
@@ -152408,7 +152765,7 @@ var require_local_auth_addon = __commonJS({
152408
152765
  "web",
152409
152766
  "other"
152410
152767
  ];
152411
- function parseRecord(data) {
152768
+ function parseRecord$1(data) {
152412
152769
  const id = str$1(data, "id");
152413
152770
  const userId = str$1(data, "userId");
152414
152771
  const deviceName = str$1(data, "deviceName");
@@ -152473,7 +152830,7 @@ var require_local_auth_addon = __commonJS({
152473
152830
  const kind = this.deps.deviceCredentialsKind ?? null;
152474
152831
  if (kind !== null) {
152475
152832
  for (const row of await (0, import_read_all_rows.readAllRows)(kind)) {
152476
- const record = parseRecord({
152833
+ const record = parseRecord$1({
152477
152834
  id: row.id,
152478
152835
  ...row.data
152479
152836
  });
@@ -152483,7 +152840,7 @@ var require_local_auth_addon = __commonJS({
152483
152840
  }
152484
152841
  const rows = await this.store.query.query({ collection: DEVICE_CREDENTIALS_COLLECTION });
152485
152842
  for (const row of rows) {
152486
- const record = parseRecord(row.data);
152843
+ const record = parseRecord$1(row.data);
152487
152844
  if (record !== null) this.records.set(record.id, record);
152488
152845
  }
152489
152846
  }
@@ -152884,7 +153241,6 @@ var require_local_auth_addon = __commonJS({
152884
153241
  }
152885
153242
  };
152886
153243
  var USERS_COLLECTION$1 = "users";
152887
- var API_KEYS_COLLECTION = "api_keys";
152888
153244
  var SCOPED_TOKENS_COLLECTION = "scoped_tokens";
152889
153245
  var USER_TOTP_COLLECTION = "user_totp";
152890
153246
  var USER_EXTERNAL_IDENTITIES_COLLECTION = "user_external_identities";
@@ -152934,52 +153290,6 @@ var require_local_auth_addon = __commonJS({
152934
153290
  notNull: true
152935
153291
  }
152936
153292
  ];
152937
- var API_KEYS_COLUMNS = [
152938
- {
152939
- name: "id",
152940
- type: "TEXT",
152941
- primaryKey: true,
152942
- notNull: true
152943
- },
152944
- {
152945
- name: "label",
152946
- type: "TEXT",
152947
- notNull: true
152948
- },
152949
- {
152950
- name: "isAdmin",
152951
- type: "BOOLEAN",
152952
- notNull: true
152953
- },
152954
- {
152955
- name: "tokenHash",
152956
- type: "TEXT",
152957
- notNull: true,
152958
- unique: true
152959
- },
152960
- {
152961
- name: "tokenPrefix",
152962
- type: "TEXT",
152963
- notNull: true
152964
- },
152965
- {
152966
- name: "allowedProviders",
152967
- type: "JSON"
152968
- },
152969
- {
152970
- name: "allowedDevices",
152971
- type: "JSON"
152972
- },
152973
- {
152974
- name: "createdAt",
152975
- type: "INTEGER",
152976
- notNull: true
152977
- },
152978
- {
152979
- name: "lastUsedAt",
152980
- type: "INTEGER"
152981
- }
152982
- ];
152983
153293
  var USER_TOTP_COLUMNS = [
152984
153294
  {
152985
153295
  name: "userId",
@@ -153091,14 +153401,6 @@ var require_local_auth_addon = __commonJS({
153091
153401
  collection: USERS_COLLECTION$1,
153092
153402
  columns: USERS_COLUMNS
153093
153403
  });
153094
- if (!skip.has("api_keys")) await store.declareCollection.mutate({
153095
- collection: API_KEYS_COLLECTION,
153096
- columns: API_KEYS_COLUMNS,
153097
- indexes: [{
153098
- name: "idx_api_keys_token_prefix",
153099
- columns: ["tokenPrefix"]
153100
- }]
153101
- });
153102
153404
  if (!skip.has("scoped_tokens")) await store.declareCollection.mutate({
153103
153405
  collection: SCOPED_TOKENS_COLLECTION,
153104
153406
  columns: SCOPED_TOKENS_COLUMNS,
@@ -153158,7 +153460,6 @@ var require_local_auth_addon = __commonJS({
153158
153460
  }
153159
153461
  var DAY_MS = 864e5;
153160
153462
  var UserBodySchema = require_dist10.UserRecordSchema.omit({ id: true });
153161
- var ApiKeyBodySchema = require_dist10.ApiKeyRecordSchema.omit({ id: true });
153162
153463
  var ScopedTokenBodySchema = require_dist10.ScopedTokenSchema.omit({ id: true });
153163
153464
  var AdminTokenBodySchema = zod.z.object({
153164
153465
  createdBy: zod.z.string(),
@@ -153246,18 +153547,6 @@ var require_local_auth_addon = __commonJS({
153246
153547
  }],
153247
153548
  retention: { none: "row goes only when an operator deletes the user; destructive declareCollection rebuild wipes all accounts" }
153248
153549
  },
153249
- "api-keys": {
153250
- schema: ApiKeyBodySchema,
153251
- class: "config",
153252
- writeTrigger: "legacy list/revoke only \u2014 nothing creates new API keys",
153253
- device: "none",
153254
- at: "none",
153255
- indexes: [{
153256
- name: "prefix",
153257
- fields: ["tokenPrefix"]
153258
- }],
153259
- retention: { none: "explicit revoke only" }
153260
- },
153261
153550
  "scoped-tokens": {
153262
153551
  schema: ScopedTokenBodySchema,
153263
153552
  class: "config",
@@ -153394,7 +153683,6 @@ var require_local_auth_addon = __commonJS({
153394
153683
  });
153395
153684
  var localAuthRecordKinds = _localAuthRecordKinds;
153396
153685
  var localAuthUsersRecordKind = _localAuthRecordKinds.users;
153397
- var localAuthApiKeysRecordKind = _localAuthRecordKinds["api-keys"];
153398
153686
  _localAuthRecordKinds["scoped-tokens"];
153399
153687
  _localAuthRecordKinds["admin-tokens"];
153400
153688
  var localAuthLoginSessionsRecordKind = _localAuthRecordKinds["login-sessions"];
@@ -153406,7 +153694,6 @@ var require_local_auth_addon = __commonJS({
153406
153694
  var localAuthAuthAuditRecordKind = _localAuthRecordKinds["auth-audit"];
153407
153695
  var LOCAL_AUTH_RECORDS_LEGACY_COLLECTIONS = [
153408
153696
  USERS_COLLECTION$1,
153409
- API_KEYS_COLLECTION,
153410
153697
  SCOPED_TOKENS_COLLECTION,
153411
153698
  ADMIN_TOKENS_COLLECTION,
153412
153699
  LOGIN_SESSIONS_COLLECTION,
@@ -153419,7 +153706,6 @@ var require_local_auth_addon = __commonJS({
153419
153706
  function localAuthRecordStoresOf(records) {
153420
153707
  return {
153421
153708
  users: records.kind(localAuthUsersRecordKind),
153422
- apiKeys: records.kind(localAuthApiKeysRecordKind),
153423
153709
  loginSessions: records.kind(localAuthLoginSessionsRecordKind),
153424
153710
  loginSessionCutoffs: records.kind(localAuthLoginSessionCutoffsRecordKind),
153425
153711
  oauthSessions: records.kind(localAuthOauthSessionsRecordKind),
@@ -154251,11 +154537,21 @@ var require_local_auth_addon = __commonJS({
154251
154537
  if (internal === null || typeof internal !== "object") return null;
154252
154538
  return internal;
154253
154539
  }
154540
+ function parseRecord(kind, schema, data) {
154541
+ try {
154542
+ return schema.parse(data);
154543
+ } catch (err) {
154544
+ const topKeys = data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).join(", ") || "(empty)" : `(non-object: ${typeof data})`;
154545
+ const detail = err instanceof Error ? err.message : String(err);
154546
+ const hint = data && typeof data === "object" && !Array.isArray(data) && Object.keys(data).length === 1 && "data" in data ? " This shape is the legacy double-wrap from a stale settings-store query path. Restart the server with the latest @camstack/system build." : "";
154547
+ throw new Error(`Failed to parse ${kind} from settings store. Top-level keys=[${topKeys}].${hint} Underlying: ${detail}`, { cause: err });
154548
+ }
154549
+ }
154254
154550
  var USERS_COLLECTION = "users";
154255
154551
  var FIRST_BOOT_ADMIN_USERNAME = "admin";
154256
154552
  var FIRST_BOOT_ADMIN_PASSWORD = "changeme";
154257
154553
  function parseUser(data) {
154258
- return parseRecord$2("user", require_dist10.UserRecordSchema, data);
154554
+ return parseRecord("user", require_dist10.UserRecordSchema, data);
154259
154555
  }
154260
154556
  function userToBody(user) {
154261
154557
  const { id: _id, ...body } = user;
@@ -157071,7 +157367,6 @@ var require_local_auth_addon = __commonJS({
157071
157367
  var LocalAuthAddon = class extends require_dist10.BaseAddon {
157072
157368
  authManager = null;
157073
157369
  userManager = null;
157074
- apiKeyManager = null;
157075
157370
  oauthSessionManager = null;
157076
157371
  reapTimer = null;
157077
157372
  totpManager = null;
@@ -157107,10 +157402,6 @@ var require_local_auth_addon = __commonJS({
157107
157402
  usersKind: authStores.users,
157108
157403
  legacyStore: store
157109
157404
  }, this.authManager);
157110
- this.apiKeyManager = new ApiKeyManager({
157111
- apiKeysKind: authStores.apiKeys,
157112
- legacyStore: store
157113
- });
157114
157405
  this.oauthSessionManager = new OauthSessionManager({ oauthSessionsKind: authStores.oauthSessions });
157115
157406
  this.totpManager = new TotpManager({
157116
157407
  userTotpKind: authStores.userTotp,
@@ -157275,15 +157566,6 @@ var require_local_auth_addon = __commonJS({
157275
157566
  totpEnabled
157276
157567
  };
157277
157568
  },
157278
- listApiKeys: async () => {
157279
- if (!this.apiKeyManager) return [];
157280
- return this.apiKeyManager.listAll();
157281
- },
157282
- revokeApiKey: async (input) => {
157283
- if (!this.apiKeyManager) throw new Error("API key management not available");
157284
- await this.apiKeyManager.revoke(input.id);
157285
- return { success: true };
157286
- },
157287
157569
  oauthIssueCode: async (input) => {
157288
157570
  return lazyOauthGrants().oauthIssueCode(input);
157289
157571
  },
@@ -157644,7 +157926,6 @@ var require_local_auth_addon = __commonJS({
157644
157926
  }
157645
157927
  this.authManager = null;
157646
157928
  this.userManager = null;
157647
- this.apiKeyManager = null;
157648
157929
  this.oauthSessionManager = null;
157649
157930
  this.externalIdentities = null;
157650
157931
  this.loginSessions = null;
@@ -157653,7 +157934,6 @@ var require_local_auth_addon = __commonJS({
157653
157934
  this.deviceCa = null;
157654
157935
  }
157655
157936
  };
157656
- exports.ApiKeyManager = ApiKeyManager;
157657
157937
  exports.AuthAuditLog = AuthAuditLog;
157658
157938
  exports.AuthManager = AuthManager;
157659
157939
  exports.DeviceCaStore = DeviceCaStore;
@@ -157831,7 +158111,7 @@ var require_loki_logging = __commonJS({
157831
158111
  [Symbol.toStringTag]: { value: "Module" }
157832
158112
  });
157833
158113
  require_chunk_Cek0wNdY();
157834
- var require_dist10 = require_dist_D9aw_d0G();
158114
+ var require_dist10 = require_dist_QyW9hVO2();
157835
158115
  var require_log_read_filter = require_log_read_filter_Bi066jwU();
157836
158116
  var zod = require_zod();
157837
158117
  function sanitizeLabelName(raw) {
@@ -158792,7 +159072,7 @@ var require_native_metrics_addon = __commonJS({
158792
159072
  [Symbol.toStringTag]: { value: "Module" }
158793
159073
  });
158794
159074
  var require_chunk = require_chunk_Cek0wNdY();
158795
- var require_dist10 = require_dist_D9aw_d0G();
159075
+ var require_dist10 = require_dist_QyW9hVO2();
158796
159076
  var node_fs_promises = __require("fs/promises");
158797
159077
  var node_util = __require("util");
158798
159078
  var node_os = __require("os");
@@ -161359,7 +161639,7 @@ var require_device_history_addon = __commonJS({
161359
161639
  [Symbol.toStringTag]: { value: "Module" }
161360
161640
  });
161361
161641
  require_chunk_Cek0wNdY();
161362
- var require_dist10 = require_dist_D9aw_d0G();
161642
+ var require_dist10 = require_dist_QyW9hVO2();
161363
161643
  var FIVE_MINUTES_MS = 5 * 6e4;
161364
161644
  var HOUR_MS = 60 * 6e4;
161365
161645
  var DAY_MS = 24 * HOUR_MS;
@@ -164405,7 +164685,7 @@ var require_filesystem_storage_addon = __commonJS({
164405
164685
  [Symbol.toStringTag]: { value: "Module" }
164406
164686
  });
164407
164687
  var require_chunk = require_chunk_Cek0wNdY();
164408
- var require_dist10 = require_dist_D9aw_d0G();
164688
+ var require_dist10 = require_dist_QyW9hVO2();
164409
164689
  var node_crypto = __require("crypto");
164410
164690
  var node_fs_promises = __require("fs/promises");
164411
164691
  var node_path = __require("path");
@@ -165515,12 +165795,12 @@ var require_lib = __commonJS({
165515
165795
  }
165516
165796
  });
165517
165797
 
165518
- // ../system/dist/wal-maintenance-jXcOxm2T.js
165519
- var require_wal_maintenance_jXcOxm2T = __commonJS({
165520
- "../system/dist/wal-maintenance-jXcOxm2T.js"(exports) {
165798
+ // ../system/dist/wal-maintenance-BIpPCYDi.js
165799
+ var require_wal_maintenance_BIpPCYDi = __commonJS({
165800
+ "../system/dist/wal-maintenance-BIpPCYDi.js"(exports) {
165521
165801
  "use strict";
165522
165802
  var require_chunk = require_chunk_Cek0wNdY();
165523
- var require_dist10 = require_dist_D9aw_d0G();
165803
+ var require_dist10 = require_dist_QyW9hVO2();
165524
165804
  var require_prefix_range = require_prefix_range_D_KueXbQ();
165525
165805
  var node_crypto = __require("crypto");
165526
165806
  var node_module = __require("module");
@@ -165980,7 +166260,7 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
165980
166260
  database: asDatabase(row.database),
165981
166261
  hash: row.manifest_hash,
165982
166262
  state: asState(row.state),
165983
- declaration: require_dist10.RecordKindDeclarationSchema.parse(JSON.parse(row.declaration))
166263
+ declaration: require_dist10.StoredRecordKindDeclarationSchema.parse(JSON.parse(row.declaration))
165984
166264
  };
165985
166265
  }
165986
166266
  function ensureRecordsSchema(db) {
@@ -166020,8 +166300,10 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166020
166300
  state = "created";
166021
166301
  } else {
166022
166302
  kindId = prior.kindId;
166023
- if (prior.hash === hash) state = "unchanged";
166024
- else {
166303
+ if (prior.hash === hash) {
166304
+ db.prepare("UPDATE _record_kinds SET declaration = ? WHERE kind_id = ? AND declaration <> ?").run(JSON.stringify(declaration), kindId, JSON.stringify(declaration));
166305
+ state = "unchanged";
166306
+ } else {
166025
166307
  db.prepare("UPDATE _record_kinds SET manifest_hash = ?, declaration = ?, state = 'declared', orphaned_at = NULL WHERE kind_id = ?").run(hash, JSON.stringify(declaration), kindId);
166026
166308
  state = "updated";
166027
166309
  }
@@ -166048,8 +166330,7 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166048
166330
  result: {
166049
166331
  kindId,
166050
166332
  state,
166051
- createdIndexes: created,
166052
- adoptionPending: null
166333
+ createdIndexes: created
166053
166334
  }
166054
166335
  };
166055
166336
  })();
@@ -166679,13 +166960,17 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166679
166960
  }
166680
166961
  async patch(input) {
166681
166962
  const k = this.kindOf(input.owner, input.kind);
166682
- const decl = k.declaration;
166683
166963
  const nowMs = this.now();
166964
+ return this.timed("patch", input.kind, () => this.db.transaction(() => this.patchRecord(k, input, nowMs))());
166965
+ }
166966
+ /** One patch, inside the caller's transaction (shared with `transact`). */
166967
+ patchRecord(k, input, nowMs) {
166968
+ const decl = k.declaration;
166684
166969
  if (input.at !== void 0 && decl.at !== "required") throw new require_dist10.InvalidRecordError(`${input.kind}: declared at: "none"`);
166685
166970
  if (input.at === null) throw new require_dist10.InvalidRecordError(`${input.kind}: "at" cannot be removed`);
166686
166971
  if (input.expiresAt !== void 0 && decl.secretPaths.length > 0) throw new require_dist10.InvalidRecordError(`${input.kind}: a kind with secret fields cannot expire by the engine (its keychain values would be orphaned)`);
166687
166972
  if (input.expiresAt !== void 0 && "ttlMs" in decl.retention) throw new require_dist10.InvalidRecordError(`${input.kind}: expiresAt is set by the engine`);
166688
- const run = this.db.transaction(() => {
166973
+ {
166689
166974
  const hasSecrets = decl.secretPaths.length > 0;
166690
166975
  const before = hasSecrets || input.ifRev !== void 0 ? this.storedRow(k, input.id) : void 0;
166691
166976
  const checked = enforceSecrets(input.owner, input.kind, decl, input.id, input.data, before === void 0 ? null : parseBody(before.data), "patch");
@@ -166722,22 +167007,83 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166722
167007
  rev: updated.rev,
166723
167008
  releasedRefs: released
166724
167009
  };
166725
- });
166726
- return this.timed("patch", input.kind, () => run());
167010
+ }
166727
167011
  }
166728
167012
  refsOfRows(k, rows) {
166729
167013
  if (k.declaration.secretPaths.length === 0) return [];
166730
167014
  return rows.flatMap((row) => [...markersOf(k.declaration, parseBody(row.data)).values()]);
166731
167015
  }
166732
167016
  async delete(input) {
166733
- const k = this.kindOf(input.owner, input.kind);
167017
+ return this.deleteRecord(this.kindOf(input.owner, input.kind), input.id);
167018
+ }
167019
+ /** One delete (shared with `transact`). */
167020
+ deleteRecord(k, id) {
166734
167021
  const hasSecrets = k.declaration.secretPaths.length > 0;
166735
- const rows = this.db.prepare(`DELETE FROM records WHERE ${kindClause(k.kindId)} AND id = ? RETURNING ${hasSecrets ? "json(data)" : "'{}'"} AS data`).all(input.id);
167022
+ const rows = this.db.prepare(`DELETE FROM records WHERE ${kindClause(k.kindId)} AND id = ? RETURNING ${hasSecrets ? "json(data)" : "'{}'"} AS data`).all(id);
166736
167023
  return {
166737
167024
  deleted: rows.length > 0,
166738
167025
  secretRefs: this.refsOfRows(k, rows)
166739
167026
  };
166740
167027
  }
167028
+ /**
167029
+ * Several put / patch / delete in ONE SQLite transaction. The scope rule
167030
+ * (one file, one `transactFamily`) is checked before a row moves; each op then
167031
+ * runs the very code of the single-row write, so secrets, indexes and size
167032
+ * bounds behave exactly as there. Any op throwing rolls the whole call back.
167033
+ */
167034
+ async transact(input) {
167035
+ const kinds = /* @__PURE__ */ new Map();
167036
+ for (const op of input.ops) if (!kinds.has(op.kind)) kinds.set(op.kind, this.kindOf(input.owner, op.kind));
167037
+ require_dist10.assertTransactScope([...kinds.values()].map((k) => ({
167038
+ kind: k.kind,
167039
+ declaration: k.declaration
167040
+ })));
167041
+ const nowMs = this.now();
167042
+ const results = [];
167043
+ const releasedRefs = [];
167044
+ const secretRefs = [];
167045
+ const label = [...kinds.keys()].join("+");
167046
+ this.timed("transact", label, () => this.db.transaction(() => {
167047
+ for (const op of input.ops) {
167048
+ const k = kinds.get(op.kind);
167049
+ if (k === void 0) throw new require_dist10.UnknownRecordKindError(`"${input.owner}" declared no kind "${op.kind}"`);
167050
+ if (op.op === "put") {
167051
+ const w = this.writeRecord(input.owner, k, op.record, op.ifRev, nowMs);
167052
+ releasedRefs.push(...w.releasedRefs);
167053
+ results.push({
167054
+ rev: w.rev,
167055
+ deleted: false
167056
+ });
167057
+ } else if (op.op === "patch") {
167058
+ const w = this.patchRecord(k, {
167059
+ ...op,
167060
+ owner: input.owner
167061
+ }, nowMs);
167062
+ releasedRefs.push(...w.releasedRefs);
167063
+ results.push({
167064
+ rev: w.rev,
167065
+ deleted: false
167066
+ });
167067
+ } else {
167068
+ const d = this.deleteRecord(k, op.id);
167069
+ secretRefs.push(...d.secretRefs);
167070
+ results.push({
167071
+ rev: null,
167072
+ deleted: d.deleted
167073
+ });
167074
+ }
167075
+ }
167076
+ })());
167077
+ for (const [name, k] of kinds) {
167078
+ const devices = input.ops.flatMap((op) => op.op === "put" && op.kind === name ? [op.record.deviceId] : []);
167079
+ if (devices.length > 0) this.afterWrite(k, devices);
167080
+ }
167081
+ return {
167082
+ results,
167083
+ releasedRefs,
167084
+ secretRefs
167085
+ };
167086
+ }
166741
167087
  async deleteMany(input) {
166742
167088
  const k = this.kindOf(input.owner, input.kind);
166743
167089
  const hasSecrets = k.declaration.secretPaths.length > 0;
@@ -166892,6 +167238,7 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
166892
167238
  "histogram",
166893
167239
  "aggregate",
166894
167240
  "deleteWhere",
167241
+ "transact",
166895
167242
  "deleteDevice",
166896
167243
  "allocateId",
166897
167244
  "listKinds",
@@ -169637,9 +169984,9 @@ var require_sqlite_settings_addon = __commonJS({
169637
169984
  [Symbol.toStringTag]: { value: "Module" }
169638
169985
  });
169639
169986
  var require_chunk = require_chunk_Cek0wNdY();
169640
- var require_dist10 = require_dist_D9aw_d0G();
169987
+ var require_dist10 = require_dist_QyW9hVO2();
169641
169988
  var require_retired_settings_keys = require_retired_settings_keys_CGUqX_Oz();
169642
- var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
169989
+ var require_wal_maintenance = require_wal_maintenance_BIpPCYDi();
169643
169990
  var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
169644
169991
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
169645
169992
  var node_fs_promises = __require("fs/promises");
@@ -170812,12 +171159,6 @@ var require_sqlite_settings_addon = __commonJS({
170812
171159
  function keyOf(owner, kind) {
170813
171160
  return `${owner}\0${kind}`;
170814
171161
  }
170815
- function withoutRetiredKeys(declaration) {
170816
- return {
170817
- ...declaration,
170818
- adoptsFrom: void 0
170819
- };
170820
- }
170821
171162
  var RecordsProvider = class {
170822
171163
  router;
170823
171164
  logger;
@@ -170851,7 +171192,7 @@ var require_sqlite_settings_addon = __commonJS({
170851
171192
  const owner = recordsCallerOf(input);
170852
171193
  const byDatabase = /* @__PURE__ */ new Map();
170853
171194
  const parsed = /* @__PURE__ */ new Map();
170854
- for (const [kind, raw] of Object.entries(input.kinds)) parsed.set(kind, withoutRetiredKeys(require_dist10.RecordKindDeclarationSchema.parse(raw)));
171195
+ for (const [kind, raw] of Object.entries(input.kinds)) parsed.set(kind, require_dist10.RecordKindDeclarationSchema.parse(raw));
170855
171196
  await this.assertFamiliesInOneFile(owner, parsed);
170856
171197
  for (const [kind, declaration] of parsed) {
170857
171198
  const known = this.placement.get(keyOf(owner, kind));
@@ -170995,6 +171336,27 @@ var require_sqlite_settings_addon = __commonJS({
170995
171336
  owner
170996
171337
  });
170997
171338
  }
171339
+ /**
171340
+ * All ops must resolve to ONE file (`records/transact-refused` `cross-file`
171341
+ * otherwise); that file's engine then checks the family and runs one SQLite
171342
+ * transaction.
171343
+ */
171344
+ async transact(input) {
171345
+ const owner = recordsCallerOf(input);
171346
+ const files = /* @__PURE__ */ new Map();
171347
+ for (const op of input.ops) {
171348
+ const database = this.placement.get(keyOf(owner, op.kind));
171349
+ if (database === void 0) throw new require_dist10.UnknownRecordKindError(`"${owner}" declared no kind "${op.kind}"`);
171350
+ files.set(database, [...files.get(database) ?? [], op.kind]);
171351
+ }
171352
+ if (files.size > 1) throw new require_dist10.TransactRefusedError(`cross-file: the ops span more than one database file (${[...files.entries()].map(([db, kinds]) => `${[...new Set(kinds)].join("+")}@${db}`).join(", ")}); a transaction lives in ONE file`);
171353
+ const first = input.ops[0];
171354
+ if (first === void 0) throw new require_dist10.InvalidRecordError("transact: no ops");
171355
+ return (await this.fileOf(owner, first.kind)).records("transact", {
171356
+ ...input,
171357
+ owner
171358
+ });
171359
+ }
170998
171360
  async allocateId(input) {
170999
171361
  const owner = recordsCallerOf(input);
171000
171362
  return (await this.fileOf(owner, input.kind)).records("allocateId", {
@@ -171252,7 +171614,7 @@ var require_sqlite_storage = __commonJS({
171252
171614
  });
171253
171615
  require_chunk_Cek0wNdY();
171254
171616
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
171255
- var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
171617
+ var require_wal_maintenance = require_wal_maintenance_BIpPCYDi();
171256
171618
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
171257
171619
  var ConfigStore = class {
171258
171620
  db;
@@ -171336,7 +171698,7 @@ var require_storage_orchestrator_addon = __commonJS({
171336
171698
  [Symbol.toStringTag]: { value: "Module" }
171337
171699
  });
171338
171700
  var require_chunk = require_chunk_Cek0wNdY();
171339
- var require_dist10 = require_dist_D9aw_d0G();
171701
+ var require_dist10 = require_dist_QyW9hVO2();
171340
171702
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
171341
171703
  var zod = require_zod();
171342
171704
  var node_crypto = __require("crypto");
@@ -175923,12 +176285,12 @@ var require_storage_orchestrator = __commonJS({
175923
176285
  }
175924
176286
  });
175925
176287
 
175926
- // ../system/dist/agent-https-DhFIbEwN.js
175927
- var require_agent_https_DhFIbEwN = __commonJS({
175928
- "../system/dist/agent-https-DhFIbEwN.js"(exports) {
176288
+ // ../system/dist/agent-https-OIvfjiTx.js
176289
+ var require_agent_https_OIvfjiTx = __commonJS({
176290
+ "../system/dist/agent-https-OIvfjiTx.js"(exports) {
175929
176291
  "use strict";
175930
176292
  var require_chunk = require_chunk_Cek0wNdY();
175931
- var require_dist10 = require_dist_D9aw_d0G();
176293
+ var require_dist10 = require_dist_QyW9hVO2();
175932
176294
  var require_x509_es = require_x509_es_C4cOo48M();
175933
176295
  var zod = require_zod();
175934
176296
  var node_crypto = __require("crypto");
@@ -176986,11 +177348,11 @@ var require_agent_https_DhFIbEwN = __commonJS({
176986
177348
  }
176987
177349
  });
176988
177350
 
176989
- // ../system/dist/constants-5mrGZxwS.js
176990
- var require_constants_5mrGZxwS = __commonJS({
176991
- "../system/dist/constants-5mrGZxwS.js"(exports) {
177351
+ // ../system/dist/constants-CdgJF4V6.js
177352
+ var require_constants_CdgJF4V6 = __commonJS({
177353
+ "../system/dist/constants-CdgJF4V6.js"(exports) {
176992
177354
  "use strict";
176993
- var MESH_CA_KEY_REF = require_dist_D9aw_d0G().buildSecretRef({
177355
+ var MESH_CA_KEY_REF = require_dist_QyW9hVO2().buildSecretRef({
176994
177356
  owner: "system",
176995
177357
  scope: { kind: "global" },
176996
177358
  fieldPath: "meshCaKey"
@@ -194087,11 +194449,11 @@ var require_system_config_addon = __commonJS({
194087
194449
  [Symbol.toStringTag]: { value: "Module" }
194088
194450
  });
194089
194451
  var require_chunk = require_chunk_Cek0wNdY();
194090
- var require_dist10 = require_dist_D9aw_d0G();
194452
+ var require_dist10 = require_dist_QyW9hVO2();
194091
194453
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
194092
194454
  var require_x509_es = require_x509_es_C4cOo48M();
194093
- var require_agent_https = require_agent_https_DhFIbEwN();
194094
- var require_constants$8 = require_constants_5mrGZxwS();
194455
+ var require_agent_https = require_agent_https_OIvfjiTx();
194456
+ var require_constants$8 = require_constants_CdgJF4V6();
194095
194457
  var require_src$1 = require_src_CnAqG6EF();
194096
194458
  var zod = require_zod();
194097
194459
  var node_crypto = __require("crypto");
@@ -275143,7 +275505,7 @@ var require_winston_logging = __commonJS({
275143
275505
  [Symbol.toStringTag]: { value: "Module" }
275144
275506
  });
275145
275507
  var require_chunk = require_chunk_Cek0wNdY();
275146
- var require_dist10 = require_dist_D9aw_d0G();
275508
+ var require_dist10 = require_dist_QyW9hVO2();
275147
275509
  var require_formatter = require_formatter_DqAKDlvN();
275148
275510
  var require_log_file_read_protocol = require_log_file_read_protocol_D0WcLbIV();
275149
275511
  var node_path = __require("path");
@@ -282946,14 +283308,14 @@ var require_lib_8oZrELLm = __commonJS({
282946
283308
  }
282947
283309
  });
282948
283310
 
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) {
283311
+ // ../system/dist/hub-mdns-ciao-CWkX17zX.js
283312
+ var require_hub_mdns_ciao_CWkX17zX = __commonJS({
283313
+ "../system/dist/hub-mdns-ciao-CWkX17zX.js"(exports) {
282952
283314
  "use strict";
282953
283315
  var require_chunk = require_chunk_Cek0wNdY();
282954
- var require_dist10 = require_dist_D9aw_d0G();
283316
+ var require_dist10 = require_dist_QyW9hVO2();
282955
283317
  var require_x509_es = require_x509_es_C4cOo48M();
282956
- var require_agent_https = require_agent_https_DhFIbEwN();
283318
+ var require_agent_https = require_agent_https_OIvfjiTx();
282957
283319
  var node_crypto = __require("crypto");
282958
283320
  var _camstack_types_node = require_node();
282959
283321
  var node_fs_promises = __require("fs/promises");
@@ -283965,12 +284327,12 @@ var require_platform_key_source_Di7HrlGR = __commonJS({
283965
284327
  }
283966
284328
  });
283967
284329
 
283968
- // ../system/dist/restore-archive-6zkRREHO.js
283969
- var require_restore_archive_6zkRREHO = __commonJS({
283970
- "../system/dist/restore-archive-6zkRREHO.js"(exports) {
284330
+ // ../system/dist/restore-archive-DMgpNgX5.js
284331
+ var require_restore_archive_DMgpNgX5 = __commonJS({
284332
+ "../system/dist/restore-archive-DMgpNgX5.js"(exports) {
283971
284333
  "use strict";
283972
284334
  var require_chunk = require_chunk_Cek0wNdY();
283973
- var require_dist10 = require_dist_D9aw_d0G();
284335
+ var require_dist10 = require_dist_QyW9hVO2();
283974
284336
  var zod = require_zod();
283975
284337
  var node_crypto = __require("crypto");
283976
284338
  var buffer = __require("buffer");
@@ -295211,9 +295573,9 @@ var require_dist3 = __commonJS({
295211
295573
  "use strict";
295212
295574
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
295213
295575
  var require_chunk = require_chunk_Cek0wNdY();
295214
- var require_dist10 = require_dist_D9aw_d0G();
295576
+ var require_dist10 = require_dist_QyW9hVO2();
295577
+ var require_device_ca = require_device_ca_DpvQ5wrb();
295215
295578
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
295216
- var require_device_ca = require_device_ca_B3xUzps7();
295217
295579
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
295218
295580
  require_alerts();
295219
295581
  var require_builtins_calendars_calendars_addon = require_calendars_addon();
@@ -295237,21 +295599,21 @@ var require_dist3 = __commonJS({
295237
295599
  var require_builtins_native_metrics_native_metrics_addon = require_native_metrics_addon();
295238
295600
  var require_builtins_device_history_device_history_addon = require_device_history_addon();
295239
295601
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
295240
- var require_wal_maintenance = require_wal_maintenance_jXcOxm2T();
295602
+ var require_wal_maintenance = require_wal_maintenance_BIpPCYDi();
295241
295603
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
295242
295604
  var require_builtins_sqlite_storage_index = require_sqlite_storage();
295243
295605
  var require_builtins_storage_orchestrator_storage_orchestrator_addon = require_storage_orchestrator_addon();
295244
295606
  require_storage_orchestrator();
295245
- var require_agent_https = require_agent_https_DhFIbEwN();
295246
- var require_constants15 = require_constants_5mrGZxwS();
295607
+ var require_agent_https = require_agent_https_OIvfjiTx();
295608
+ var require_constants15 = require_constants_CdgJF4V6();
295247
295609
  var require_builtins_system_config_system_config_addon = require_system_config_addon();
295248
295610
  require_system_config();
295249
295611
  var require_builtins_winston_logging_index = require_winston_logging();
295250
295612
  var require_custom_action_registry = require_custom_action_registry_MRyes5j0();
295251
- var require_hub_mdns_ciao = require_hub_mdns_ciao_CFlhVKK6();
295613
+ var require_hub_mdns_ciao = require_hub_mdns_ciao_CWkX17zX();
295252
295614
  var require_platform_key_source = require_platform_key_source_Di7HrlGR();
295253
295615
  var require_resource_monitor = require_resource_monitor_mio9dSCT();
295254
- var require_restore_archive = require_restore_archive_6zkRREHO();
295616
+ var require_restore_archive = require_restore_archive_DMgpNgX5();
295255
295617
  var require_coral_accelerators = require_coral_accelerators_oUXmmbc2();
295256
295618
  var zod = require_zod();
295257
295619
  var node_crypto = __require("crypto");
@@ -308266,6 +308628,7 @@ var require_dist3 = __commonJS({
308266
308628
  histogram: (input) => r.histogram.query(input),
308267
308629
  aggregate: (input) => r.aggregate.query(input),
308268
308630
  deleteWhere: (input) => r.deleteWhere.mutate(input),
308631
+ transact: (input) => r.transact.mutate(input),
308269
308632
  deleteDevice: (input) => r.deleteDevice.mutate(input),
308270
308633
  allocateId: (input) => r.allocateId.mutate(input)
308271
308634
  };
@@ -317855,7 +318218,6 @@ var require_dist3 = __commonJS({
317855
318218
  exports.AgentMeshIdentityGate = AgentMeshIdentityGate;
317856
318219
  exports.AgentPairing = require_builtins_system_config_system_config_addon.AgentPairing;
317857
318220
  exports.AlertCenterAddon = require_builtins_alerts_alerts_addon.AlertCenterAddon;
317858
- exports.ApiKeyManager = require_builtins_local_auth_local_auth_addon.ApiKeyManager;
317859
318221
  exports.AuthAuditLog = require_builtins_local_auth_local_auth_addon.AuthAuditLog;
317860
318222
  exports.AuthManager = require_builtins_local_auth_local_auth_addon.AuthManager;
317861
318223
  exports.BackupDecryptError = require_restore_archive.BackupDecryptError;
@@ -318675,7 +319037,7 @@ var require_enums = __commonJS({
318675
319037
  "../types/dist/enums.js"(exports) {
318676
319038
  "use strict";
318677
319039
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
318678
- var require_event_category = require_event_category_eSqkye_K();
319040
+ var require_event_category = require_event_category_7AwNbPjm();
318679
319041
  var EventSourceType = /* @__PURE__ */ (function(EventSourceType2) {
318680
319042
  EventSourceType2["Addon"] = "addon";
318681
319043
  EventSourceType2["Core"] = "core";
@@ -318695,8 +319057,8 @@ var require_dist4 = __commonJS({
318695
319057
  "../types/dist/index.js"(exports) {
318696
319058
  "use strict";
318697
319059
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
318698
- var require_sleep = require_sleep_Re8daN0Y();
318699
- var require_event_category = require_event_category_eSqkye_K();
319060
+ var require_sleep = require_sleep_CD18m9HF();
319061
+ var require_event_category = require_event_category_7AwNbPjm();
318700
319062
  var require_composition = require_composition_eoYYVfOp();
318701
319063
  var require_node_color2 = require_node_color();
318702
319064
  var require_err_msg = require_err_msg_BhVbr0NX();
@@ -322967,17 +323329,6 @@ var require_dist4 = __commonJS({
322967
323329
  createdAt: zod.z.number(),
322968
323330
  updatedAt: zod.z.number()
322969
323331
  });
322970
- var ApiKeyRecordSchema = zod.z.object({
322971
- id: zod.z.string(),
322972
- label: zod.z.string(),
322973
- isAdmin: zod.z.boolean().default(false),
322974
- allowedProviders: AllowedProviderSchema,
322975
- allowedDevices: AllowedDevicesSchema,
322976
- tokenHash: zod.z.string(),
322977
- tokenPrefix: zod.z.string(),
322978
- createdAt: zod.z.number(),
322979
- lastUsedAt: zod.z.number().optional()
322980
- });
322981
323332
  var ScopedTokenSchema = zod.z.object({
322982
323333
  id: zod.z.string(),
322983
323334
  userId: zod.z.string(),
@@ -329035,15 +329386,31 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
329035
329386
  var DeclareKindResultSchema = zod.z.object({
329036
329387
  kindId: zod.z.number().int(),
329037
329388
  state: RecordKindStateSchema,
329038
- createdIndexes: zod.z.array(zod.z.string()),
329039
- /**
329040
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
329041
- * it stays on the wire, null, because an addon built before the removal reads
329042
- * an ABSENT field as "adoption pending" and refuses to start.
329043
- */
329044
- adoptionPending: zod.z.null()
329389
+ createdIndexes: zod.z.array(zod.z.string())
329045
329390
  });
329046
329391
  var SecretRefsList = zod.z.array(zod.z.string());
329392
+ var RecordTransactOpSchema = zod.z.discriminatedUnion("op", [
329393
+ zod.z.object({
329394
+ op: zod.z.literal("put"),
329395
+ kind: require_sleep.RecordKindNameSchema,
329396
+ record: RecordInputSchema,
329397
+ ifRev: zod.z.number().int().min(0).optional()
329398
+ }),
329399
+ zod.z.object({
329400
+ op: zod.z.literal("patch"),
329401
+ kind: require_sleep.RecordKindNameSchema,
329402
+ id: RecordIdSchema,
329403
+ data: RecordBodySchema,
329404
+ at: zod.z.number().int().nullable().optional(),
329405
+ expiresAt: zod.z.number().int().nullable().optional(),
329406
+ ifRev: zod.z.number().int().min(1).optional()
329407
+ }),
329408
+ zod.z.object({
329409
+ op: zod.z.literal("delete"),
329410
+ kind: require_sleep.RecordKindNameSchema,
329411
+ id: RecordIdSchema
329412
+ })
329413
+ ]);
329047
329414
  var RecordSecretRefsSchema = zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.string()));
329048
329415
  var recordsCapability = {
329049
329416
  name: "records",
@@ -329175,6 +329542,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
329175
329542
  kind: "mutation",
329176
329543
  auth: "admin"
329177
329544
  }),
329545
+ /**
329546
+ * Several single-row writes (put / patch / delete) in ONE SQLite transaction:
329547
+ * all land or none does. Every op's kind must sit in one file and share one
329548
+ * `transactFamily` (`records/transact-refused` otherwise). Results are in op order.
329549
+ */
329550
+ transact: require_sleep.method(zod.z.object({ ops: zod.z.array(RecordTransactOpSchema).min(1).max(require_sleep.RECORD_BATCH_MAX) }), zod.z.object({
329551
+ results: zod.z.array(zod.z.object({
329552
+ rev: zod.z.number().int().nullable(),
329553
+ deleted: zod.z.boolean()
329554
+ })),
329555
+ releasedRefs: SecretRefsList,
329556
+ secretRefs: SecretRefsList
329557
+ }), {
329558
+ kind: "mutation",
329559
+ auth: "admin"
329560
+ }),
329178
329561
  /** The D865 hook body: every kind of this addon declared `deviceRemoval: 'delete'`. */
329179
329562
  deleteDevice: require_sleep.method(zod.z.object({
329180
329563
  deviceId: zod.z.number().int(),
@@ -355992,9 +356375,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
355992
356375
  "node-updating",
355993
356376
  "node-inference-unavailable",
355994
356377
  "detection-blind",
356378
+ "motion-noisy",
356379
+ "motion-calm",
355995
356380
  "recording-stalled",
355996
356381
  "recording-healthy",
355997
356382
  "recording-degraded",
356383
+ "device-attention-required",
356384
+ "device-attention-resolved",
355998
356385
  "storage-location-low",
355999
356386
  "storage-location-critical",
356000
356387
  "storage-location-ok",
@@ -356018,6 +356405,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
356018
356405
  "alert-critical",
356019
356406
  "alert-error",
356020
356407
  "alert-critical-resolved",
356408
+ "rule-broken",
356409
+ "rule-repaired",
356021
356410
  "camera-online",
356022
356411
  "camera-offline",
356023
356412
  "camera-disabled",
@@ -357102,6 +357491,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
357102
357491
  value: "detection-blind",
357103
357492
  label: "Camera detecting nothing"
357104
357493
  },
357494
+ {
357495
+ value: "motion-noisy",
357496
+ label: "Camera motion constant, no subject"
357497
+ },
357498
+ {
357499
+ value: "motion-calm",
357500
+ label: "Camera motion calm again"
357501
+ },
357105
357502
  {
357106
357503
  value: "recording-stalled",
357107
357504
  label: "Recording stalled"
@@ -357114,6 +357511,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
357114
357511
  value: "recording-degraded",
357115
357512
  label: "Recording degraded (restart storm)"
357116
357513
  },
357514
+ {
357515
+ value: "device-attention-required",
357516
+ label: "Device needs attention"
357517
+ },
357518
+ {
357519
+ value: "device-attention-resolved",
357520
+ label: "Device attention resolved"
357521
+ },
357117
357522
  {
357118
357523
  value: "storage-location-low",
357119
357524
  label: "Storage location low"
@@ -357198,6 +357603,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
357198
357603
  value: "alert-critical-resolved",
357199
357604
  label: "Critical alert resolved"
357200
357605
  },
357606
+ {
357607
+ value: "rule-broken",
357608
+ label: "Notification rule broken"
357609
+ },
357610
+ {
357611
+ value: "rule-repaired",
357612
+ label: "Notification rule repaired"
357613
+ },
357201
357614
  {
357202
357615
  value: "alarm-arm-refused",
357203
357616
  label: "Alarm arm refused"
@@ -370493,6 +370906,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
370493
370906
  powerState: zod.z.string().nullable(),
370494
370907
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
370495
370908
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
370909
+ /**
370910
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
370911
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
370912
+ * when none is reported. A cleared reminder is not an unknown one.
370913
+ */
370914
+ filterCleaningDue: zod.z.boolean().nullable(),
370915
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
370916
+ machineCareDue: zod.z.boolean().nullable(),
370917
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
370918
+ machineCareRemainingRuns: zod.z.number().int().nonnegative().nullable(),
370496
370919
  /** Option states: null when the appliance does not expose the option or has not said. */
370497
370920
  halfLoad: zod.z.boolean().nullable(),
370498
370921
  hygienePlus: zod.z.boolean().nullable(),
@@ -378986,16 +379409,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
378986
379409
  allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])).optional(),
378987
379410
  scopes: zod.z.array(TokenScopeSchema).optional()
378988
379411
  });
378989
- var ApiKeySummarySchema = zod.z.object({
378990
- id: zod.z.string(),
378991
- label: zod.z.string(),
378992
- isAdmin: zod.z.boolean().default(false),
378993
- allowedProviders: zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")]).optional(),
378994
- allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])).optional(),
378995
- tokenPrefix: zod.z.string(),
378996
- createdAt: zod.z.number(),
378997
- lastUsedAt: zod.z.number().optional()
378998
- });
378999
379412
  var OauthSessionSummarySchema = zod.z.object({
379000
379413
  id: zod.z.string(),
379001
379414
  userId: zod.z.string(),
@@ -379076,12 +379489,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
379076
379489
  kind: "mutation",
379077
379490
  access: "view"
379078
379491
  }),
379079
- listApiKeys: require_sleep.method(zod.z.void(), zod.z.array(ApiKeySummarySchema), { auth: "admin" }),
379080
- revokeApiKey: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
379081
- kind: "mutation",
379082
- auth: "admin",
379083
- access: "delete"
379084
- }),
379085
379492
  setupTotp: require_sleep.method(zod.z.object({ userId: zod.z.string() }), TotpSetupResultSchema, {
379086
379493
  kind: "mutation",
379087
379494
  auth: "admin",
@@ -389768,6 +390175,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
389768
390175
  addonId: null,
389769
390176
  access: "view"
389770
390177
  },
390178
+ "records.transact": {
390179
+ capName: "records",
390180
+ capScope: "system",
390181
+ addonId: null,
390182
+ access: "create"
390183
+ },
389771
390184
  "sceneMonitor.captureReference": {
389772
390185
  capName: "scene-monitor",
389773
390186
  capScope: "device",
@@ -391100,12 +391513,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
391100
391513
  addonId: null,
391101
391514
  access: "view"
391102
391515
  },
391103
- "userManagement.listApiKeys": {
391104
- capName: "user-management",
391105
- capScope: "system",
391106
- addonId: null,
391107
- access: "view"
391108
- },
391109
391516
  "userManagement.listExternalIdentities": {
391110
391517
  capName: "user-management",
391111
391518
  capScope: "system",
@@ -391160,12 +391567,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
391160
391567
  addonId: null,
391161
391568
  access: "create"
391162
391569
  },
391163
- "userManagement.revokeApiKey": {
391164
- capName: "user-management",
391165
- capScope: "system",
391166
- addonId: null,
391167
- access: "delete"
391168
- },
391169
391570
  "userManagement.revokeOauthSession": {
391170
391571
  capName: "user-management",
391171
391572
  capScope: "system",
@@ -399425,8 +399826,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
399425
399826
  resetPassword: (input) => dispatch("userManagement", "resetPassword", "mutation", input),
399426
399827
  setUserScopes: (input) => dispatch("userManagement", "setUserScopes", "mutation", input),
399427
399828
  validateCredentials: (input) => dispatch("userManagement", "validateCredentials", "mutation", input),
399428
- listApiKeys: (input) => dispatch("userManagement", "listApiKeys", "query", input),
399429
- revokeApiKey: (input) => dispatch("userManagement", "revokeApiKey", "mutation", input),
399430
399829
  setupTotp: (input) => dispatch("userManagement", "setupTotp", "mutation", input),
399431
399830
  confirmTotp: (input) => dispatch("userManagement", "confirmTotp", "mutation", input),
399432
399831
  disableTotp: (input) => dispatch("userManagement", "disableTotp", "mutation", input),
@@ -399864,9 +400263,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
399864
400263
  function systemEventFilterApplies(kind, filter) {
399865
400264
  switch (filter) {
399866
400265
  case "deviceIds":
399867
- return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("recording-") || kind === "alarm-triggered";
400266
+ return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
399868
400267
  case "deviceTypes":
399869
- return kind.startsWith("device-") || kind === "detection-blind";
400268
+ return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
399870
400269
  case "nodeIds":
399871
400270
  return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated" || kind.startsWith("storage-location-") || kind.startsWith("alert-");
399872
400271
  case "packageNames":
@@ -399901,9 +400300,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
399901
400300
  "stream-online": "device-events",
399902
400301
  "stream-offline": "device-events",
399903
400302
  "detection-blind": "device-events",
400303
+ "motion-noisy": "device-events",
400304
+ "motion-calm": "device-events",
399904
400305
  "recording-stalled": "device-events",
399905
400306
  "recording-healthy": "device-events",
399906
400307
  "recording-degraded": "device-events",
400308
+ "device-attention-required": "device-events",
400309
+ "device-attention-resolved": "device-events",
399907
400310
  "node-online": "system",
399908
400311
  "node-offline": "system",
399909
400312
  "node-restarting": "system",
@@ -399920,6 +400323,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
399920
400323
  "alert-critical": "system",
399921
400324
  "alert-error": "system",
399922
400325
  "alert-critical-resolved": "system",
400326
+ "rule-broken": "system",
400327
+ "rule-repaired": "system",
399923
400328
  "storage-location-low": "system",
399924
400329
  "storage-location-critical": "system",
399925
400330
  "storage-location-ok": "system",
@@ -399995,6 +400400,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
399995
400400
  label: "Detecting nothing",
399996
400401
  kinds: ["detection-blind"]
399997
400402
  },
400403
+ {
400404
+ id: "motion-noise",
400405
+ family: "device-events",
400406
+ label: "Motion without a subject",
400407
+ kinds: ["motion-noisy", "motion-calm"]
400408
+ },
399998
400409
  {
399999
400410
  id: "recording",
400000
400411
  family: "device-events",
@@ -400005,6 +400416,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
400005
400416
  "recording-degraded"
400006
400417
  ]
400007
400418
  },
400419
+ {
400420
+ id: "device-attention",
400421
+ family: "device-events",
400422
+ label: "Needs attention",
400423
+ kinds: ["device-attention-required", "device-attention-resolved"]
400424
+ },
400008
400425
  {
400009
400426
  id: "nodes",
400010
400427
  family: "system",
@@ -400065,6 +400482,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
400065
400482
  "alert-critical-resolved"
400066
400483
  ]
400067
400484
  },
400485
+ {
400486
+ id: "rule-health",
400487
+ family: "system",
400488
+ label: "Notification rules",
400489
+ kinds: ["rule-broken", "rule-repaired"]
400490
+ },
400068
400491
  {
400069
400492
  id: "alarm",
400070
400493
  family: "alarm",
@@ -401407,6 +401830,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
401407
401830
  if (severity === "error" && phase === "raised") return "alert-error";
401408
401831
  return null;
401409
401832
  }
401833
+ function deviceAttentionKind(severity, phase) {
401834
+ if (severity !== "critical") return null;
401835
+ return phase === "raised" ? "device-attention-required" : "device-attention-resolved";
401836
+ }
401410
401837
  function alertEpisodePayload(alert, phase, at) {
401411
401838
  const nodeId = alertNodeId(alert);
401412
401839
  return {
@@ -401440,6 +401867,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
401440
401867
  "alert-error",
401441
401868
  "alert-critical-resolved"
401442
401869
  ];
401870
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
401443
401871
  var UPDATES = [
401444
401872
  "addon-update-available",
401445
401873
  "server-update-available",
@@ -401469,9 +401897,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
401469
401897
  "stream-online",
401470
401898
  "stream-offline",
401471
401899
  "detection-blind",
401900
+ "motion-noisy",
401901
+ "motion-calm",
401472
401902
  "recording-stalled",
401473
401903
  "recording-healthy",
401474
401904
  "recording-degraded",
401905
+ ...DEVICE_ATTENTION,
401475
401906
  ...ALARM
401476
401907
  ];
401477
401908
  var SUMMARISABLE = [...systemEventKindsOfFamily("device-events"), ...systemEventKindsOfFamily("system")];
@@ -402042,7 +402473,36 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402042
402473
  families: ["rule"],
402043
402474
  fields: [...RULE_TEXT],
402044
402475
  kinds: ["system"],
402045
- systemEventKinds: ["detection-blind", "recording-stalled"]
402476
+ systemEventKinds: [
402477
+ "detection-blind",
402478
+ "motion-noisy",
402479
+ "motion-calm",
402480
+ "recording-stalled"
402481
+ ]
402482
+ },
402483
+ {
402484
+ name: "duty",
402485
+ label: "Motion share (%)",
402486
+ example: "55",
402487
+ group: "system",
402488
+ families: ["rule"],
402489
+ fields: [...RULE_TEXT],
402490
+ kinds: ["system"],
402491
+ systemEventKinds: ["motion-noisy", "motion-calm"]
402492
+ },
402493
+ {
402494
+ name: "sessions",
402495
+ label: "Detection sessions",
402496
+ example: "96",
402497
+ group: "system",
402498
+ families: ["rule"],
402499
+ fields: [...RULE_TEXT],
402500
+ kinds: ["system"],
402501
+ systemEventKinds: [
402502
+ "detection-blind",
402503
+ "motion-noisy",
402504
+ "motion-calm"
402505
+ ]
402046
402506
  },
402047
402507
  {
402048
402508
  name: "message",
@@ -402052,7 +402512,52 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402052
402512
  families: ["rule"],
402053
402513
  fields: [...RULE_TEXT],
402054
402514
  kinds: ["system"],
402055
- systemEventKinds: ["recording-degraded", ...ALERT_EPISODE]
402515
+ systemEventKinds: [
402516
+ "recording-degraded",
402517
+ ...DEVICE_ATTENTION,
402518
+ ...ALERT_EPISODE
402519
+ ]
402520
+ },
402521
+ {
402522
+ name: "ruleName",
402523
+ label: "Rule name",
402524
+ example: "Robot",
402525
+ group: "system",
402526
+ families: ["rule"],
402527
+ fields: [...RULE_TEXT],
402528
+ kinds: ["system"],
402529
+ systemEventKinds: ["rule-broken", "rule-repaired"]
402530
+ },
402531
+ {
402532
+ name: "ruleId",
402533
+ label: "Rule id",
402534
+ example: "3db3e226-9b82-4681-a200-de13b260aa48",
402535
+ group: "system",
402536
+ families: ["rule"],
402537
+ fields: [...RULE_TEXT],
402538
+ kinds: ["system"],
402539
+ systemEventKinds: ["rule-broken", "rule-repaired"]
402540
+ },
402541
+ {
402542
+ name: "brokenReason",
402543
+ label: "Why the rule is broken",
402544
+ description: "unparseable, device-deleted or target-deleted",
402545
+ example: "device-deleted",
402546
+ group: "system",
402547
+ families: ["rule"],
402548
+ fields: [...RULE_TEXT],
402549
+ kinds: ["system"],
402550
+ systemEventKinds: ["rule-broken"]
402551
+ },
402552
+ {
402553
+ name: "offendingIds",
402554
+ label: "Deleted devices or destinations",
402555
+ example: "4483",
402556
+ group: "system",
402557
+ families: ["rule"],
402558
+ fields: [...RULE_TEXT],
402559
+ kinds: ["system"],
402560
+ systemEventKinds: ["rule-broken"]
402056
402561
  },
402057
402562
  {
402058
402563
  name: "locationName",
@@ -402255,7 +402760,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402255
402760
  families: ["rule"],
402256
402761
  fields: [...RULE_TEXT],
402257
402762
  kinds: ["system"],
402258
- systemEventKinds: ["export-completed", ...ALERT_EPISODE]
402763
+ systemEventKinds: [
402764
+ "export-completed",
402765
+ ...DEVICE_ATTENTION,
402766
+ ...ALERT_EPISODE
402767
+ ]
402259
402768
  },
402260
402769
  {
402261
402770
  name: "severity",
@@ -402275,7 +402784,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402275
402784
  families: ["rule"],
402276
402785
  fields: [...RULE_TEXT],
402277
402786
  kinds: ["system"],
402278
- systemEventKinds: [...ALERT_EPISODE]
402787
+ systemEventKinds: [...DEVICE_ATTENTION, ...ALERT_EPISODE]
402279
402788
  },
402280
402789
  {
402281
402790
  name: "source",
@@ -402295,7 +402804,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402295
402804
  families: ["rule"],
402296
402805
  fields: [...RULE_TEXT],
402297
402806
  kinds: ["system"],
402298
- systemEventKinds: [...ALERT_EPISODE]
402807
+ systemEventKinds: [...DEVICE_ATTENTION, ...ALERT_EPISODE]
402299
402808
  },
402300
402809
  {
402301
402810
  name: "exportId",
@@ -402494,7 +403003,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402494
403003
  "node-updating",
402495
403004
  "alert-critical",
402496
403005
  "alert-error",
402497
- "alert-critical-resolved"
403006
+ "alert-critical-resolved",
403007
+ "device-attention-required",
403008
+ "device-attention-resolved",
403009
+ "rule-broken",
403010
+ "rule-repaired"
402498
403011
  ];
402499
403012
  function servedTemplateVars() {
402500
403013
  return NC_TEMPLATE_VARS.filter((d) => !isHeldBackTemplateVar(d)).map((d) => d.systemEventKinds === void 0 ? d : {
@@ -402551,6 +403064,179 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
402551
403064
  function isKnownTemplateVar(name, ctx) {
402552
403065
  return templateVarsFor(ctx).some((d) => d.dynamic !== void 0 ? name.startsWith(d.dynamic.prefix) && name.length > d.dynamic.prefix.length : d.name === name);
402553
403066
  }
403067
+ var NC_SYSTEM_EVENT_CLASS_SPECS = [
403068
+ {
403069
+ id: "device-connectivity",
403070
+ family: "device-events",
403071
+ label: "Device connectivity (offline / back online)",
403072
+ bad: ["device-offline"],
403073
+ recovery: ["device-online"],
403074
+ snapshotLabel: "Devices offline now",
403075
+ snapshotSection: "device-state"
403076
+ },
403077
+ {
403078
+ id: "device-switch",
403079
+ family: "device-events",
403080
+ label: "Device switched off / back on",
403081
+ bad: ["device-disabled"],
403082
+ recovery: ["device-enabled"],
403083
+ snapshotLabel: "Devices switched off now",
403084
+ snapshotSection: "device-state"
403085
+ },
403086
+ {
403087
+ id: "stream-connectivity",
403088
+ family: "device-events",
403089
+ label: "Stream connectivity (offline / back online)",
403090
+ bad: ["stream-offline"],
403091
+ recovery: ["stream-online"],
403092
+ snapshotLabel: "Streams offline now",
403093
+ snapshotSection: "streams"
403094
+ },
403095
+ {
403096
+ id: "battery",
403097
+ family: "device-events",
403098
+ label: "Battery (low / back to normal)",
403099
+ bad: ["device-battery-low"],
403100
+ recovery: ["device-battery-normal"],
403101
+ snapshotLabel: "Batteries low now",
403102
+ snapshotSection: "battery"
403103
+ },
403104
+ {
403105
+ id: "consumables",
403106
+ family: "device-events",
403107
+ label: "Consumables (low / replaced)",
403108
+ bad: ["device-consumable-low"],
403109
+ recovery: ["device-consumable-normal"],
403110
+ snapshotLabel: "Consumables low now",
403111
+ snapshotSection: "consumables"
403112
+ },
403113
+ {
403114
+ id: "tanks",
403115
+ family: "device-events",
403116
+ label: "Tanks (low or full / back to normal)",
403117
+ bad: ["device-tank-low", "device-tank-full"],
403118
+ recovery: ["device-tank-normal"],
403119
+ snapshotLabel: "Tanks low or full now",
403120
+ snapshotSection: "tanks"
403121
+ },
403122
+ {
403123
+ id: "motion-noise",
403124
+ family: "device-events",
403125
+ label: "Motion without a subject (constant / calm again)",
403126
+ bad: ["motion-noisy"],
403127
+ recovery: ["motion-calm"],
403128
+ snapshotLabel: "Cameras with constant motion now",
403129
+ snapshotSection: null
403130
+ },
403131
+ {
403132
+ id: "recording-health",
403133
+ family: "device-events",
403134
+ label: "Recording health (stalled or degraded / recording again)",
403135
+ bad: ["recording-stalled", "recording-degraded"],
403136
+ recovery: ["recording-healthy"],
403137
+ snapshotLabel: "Recordings stalled now",
403138
+ snapshotSection: null
403139
+ },
403140
+ {
403141
+ id: "device-attention",
403142
+ family: "device-events",
403143
+ label: "Device needs attention (raised / resolved)",
403144
+ bad: ["device-attention-required"],
403145
+ recovery: ["device-attention-resolved"],
403146
+ snapshotLabel: "Devices needing attention now",
403147
+ snapshotSection: null
403148
+ },
403149
+ {
403150
+ id: "node-connectivity",
403151
+ family: "system",
403152
+ label: "Node connectivity (offline / back online)",
403153
+ bad: ["node-offline"],
403154
+ recovery: ["node-online"],
403155
+ snapshotLabel: "Nodes offline now",
403156
+ snapshotSection: "nodes"
403157
+ },
403158
+ {
403159
+ id: "storage-space",
403160
+ family: "system",
403161
+ label: "Storage space (low or critical / ok again)",
403162
+ bad: ["storage-location-low", "storage-location-critical"],
403163
+ recovery: ["storage-location-ok"],
403164
+ snapshotLabel: "Storage locations low now",
403165
+ snapshotSection: null
403166
+ },
403167
+ {
403168
+ id: "critical-alerts",
403169
+ family: "system",
403170
+ label: "Critical alerts (raised / resolved)",
403171
+ bad: ["alert-critical"],
403172
+ recovery: ["alert-critical-resolved"],
403173
+ snapshotLabel: "Critical alerts open now",
403174
+ snapshotSection: null
403175
+ },
403176
+ {
403177
+ id: "rule-health",
403178
+ family: "system",
403179
+ label: "Rule health (broken / repaired)",
403180
+ bad: ["rule-broken"],
403181
+ recovery: ["rule-repaired"],
403182
+ snapshotLabel: "Notification rules broken now",
403183
+ snapshotSection: null
403184
+ }
403185
+ ];
403186
+ var CLASS_BY_KIND = new Map(NC_SYSTEM_EVENT_CLASS_SPECS.flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
403187
+ function systemEventClassKinds(spec) {
403188
+ return [...spec.bad, ...spec.recovery];
403189
+ }
403190
+ function systemEventClassOf(kind) {
403191
+ return CLASS_BY_KIND.get(kind);
403192
+ }
403193
+ function isSystemEventRecoveryKind(kind) {
403194
+ return systemEventClassOf(kind)?.recovery.some((k) => k === kind) ?? false;
403195
+ }
403196
+ function systemEventClassesFor(family) {
403197
+ return NC_SYSTEM_EVENT_CLASS_SPECS.filter((spec) => spec.family === family);
403198
+ }
403199
+ function expandSystemEventClasses(kinds) {
403200
+ const out = [];
403201
+ const seen = /* @__PURE__ */ new Set();
403202
+ const push = (kind) => {
403203
+ if (seen.has(kind)) return;
403204
+ seen.add(kind);
403205
+ out.push(kind);
403206
+ };
403207
+ const listed = new Set(kinds);
403208
+ for (const kind of kinds) {
403209
+ push(kind);
403210
+ const spec = systemEventClassOf(kind);
403211
+ if (spec === void 0) continue;
403212
+ const hasBad = spec.bad.some((k) => listed.has(k));
403213
+ if (spec.bad.some((k) => k === kind)) for (const edge of spec.recovery) push(edge);
403214
+ else if (!hasBad) for (const edge of spec.bad) push(edge);
403215
+ }
403216
+ return out;
403217
+ }
403218
+ function isInstantSystemRule(rule) {
403219
+ if (rule.delivery !== "system-event") return false;
403220
+ return rule.systemEventDelivery?.mode !== "summary";
403221
+ }
403222
+ function withSystemEventClasses(rule) {
403223
+ const condition = rule.conditions.systemEvent;
403224
+ if (condition === void 0 || !isInstantSystemRule(rule)) return rule;
403225
+ const families = new Set(condition.kinds.map((kind) => NC_SYSTEM_EVENT_FAMILY[kind]));
403226
+ if (families.size !== 1 || families.has(null)) return rule;
403227
+ const kinds = expandSystemEventClasses(condition.kinds);
403228
+ if (kinds.length === condition.kinds.length) return rule;
403229
+ return {
403230
+ ...rule,
403231
+ conditions: {
403232
+ ...rule.conditions,
403233
+ systemEvent: {
403234
+ ...condition,
403235
+ kinds
403236
+ }
403237
+ }
403238
+ };
403239
+ }
402554
403240
  var NC_SYSTEM_EVENT_SUMMARY_FAMILIES = ["device-events", "system"];
402555
403241
  function systemEventSummaryScheduleOf(rule) {
402556
403242
  if (!isSystemDelivery(rule.delivery)) return null;
@@ -406637,8 +407323,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406637
407323
  exports.AlertStatusSchema = AlertStatusSchema;
406638
407324
  exports.AmbientLightSensorStatusSchema = AmbientLightSensorStatusSchema;
406639
407325
  exports.AnalyticsLtsSeriesSchema = AnalyticsLtsSeriesSchema;
406640
- exports.ApiKeyRecordSchema = ApiKeyRecordSchema;
406641
- exports.ApiKeySummarySchema = ApiKeySummarySchema;
406642
407326
  exports.AppFlowPurposeSchema = AppFlowPurposeSchema;
406643
407327
  exports.AppLoginPathSchema = AppLoginPathSchema;
406644
407328
  exports.AppPageLangSchema = AppPageLangSchema;
@@ -407626,6 +408310,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
407626
408310
  exports.NC_SERVER_PACKAGE_NAME = NC_SERVER_PACKAGE_NAME;
407627
408311
  exports.NC_SNOOZE_MAX_MINUTES = NC_SNOOZE_MAX_MINUTES;
407628
408312
  exports.NC_SYSTEM_DELIVERY = NC_SYSTEM_DELIVERY;
408313
+ exports.NC_SYSTEM_EVENT_CLASS_SPECS = NC_SYSTEM_EVENT_CLASS_SPECS;
407629
408314
  exports.NC_SYSTEM_EVENT_CONDITION_FILTER_KEYS = NC_SYSTEM_EVENT_CONDITION_FILTER_KEYS;
407630
408315
  exports.NC_SYSTEM_EVENT_FAMILIES = NC_SYSTEM_EVENT_FAMILIES;
407631
408316
  exports.NC_SYSTEM_EVENT_FAMILY = NC_SYSTEM_EVENT_FAMILY;
@@ -408024,6 +408709,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408024
408709
  exports.RecordSecretRefsSchema = RecordSecretRefsSchema;
408025
408710
  exports.RecordSecretUnavailableError = require_sleep.RecordSecretUnavailableError;
408026
408711
  exports.RecordTooLargeError = require_sleep.RecordTooLargeError;
408712
+ exports.RecordTransactOpSchema = RecordTransactOpSchema;
408027
408713
  exports.RecordTriggerSchema = RecordTriggerSchema;
408028
408714
  exports.RecordUniqueViolationError = require_sleep.RecordUniqueViolationError;
408029
408715
  exports.RecordViewSchema = RecordViewSchema;
@@ -408293,6 +408979,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408293
408979
  exports.StorageTableSchema = StorageTableSchema;
408294
408980
  exports.StorageTestLocationResultSchema = TestLocationResultSchema;
408295
408981
  exports.StorageWriteChunkInputSchema = WriteChunkInputSchema;
408982
+ exports.StoredRecordKindDeclarationSchema = require_sleep.StoredRecordKindDeclarationSchema;
408296
408983
  exports.StreamCodecSchema = StreamCodecSchema;
408297
408984
  exports.StreamFormatSchema = StreamFormatSchema;
408298
408985
  exports.StreamNetworkStatsSchema = StreamNetworkStatsSchema;
@@ -408399,6 +409086,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408399
409086
  exports.TrainingResultSchema = TrainingResultSchema;
408400
409087
  exports.TrainingSplitPlanSchema = TrainingSplitPlanSchema;
408401
409088
  exports.TrainingStageSchema = TrainingStageSchema;
409089
+ exports.TransactRefusedError = require_sleep.TransactRefusedError;
408402
409090
  exports.TransportPlaneCountsSchema = TransportPlaneCountsSchema;
408403
409091
  exports.TransportPlaneSchema = TransportPlaneSchema;
408404
409092
  exports.TurnServerSchema = TurnServerSchema;
@@ -408533,6 +409221,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408533
409221
  exports.asRecordsError = require_sleep.asRecordsError;
408534
409222
  exports.asString = require_sleep.asString;
408535
409223
  exports.assertTimelapseCadences = assertTimelapseCadences;
409224
+ exports.assertTransactScope = require_sleep.assertTransactScope;
408536
409225
  exports.assertValidDeclaration = require_sleep.assertValidDeclaration;
408537
409226
  exports.assignNodeColorId = require_node_color2.assignNodeColorId;
408538
409227
  exports.audioAnalysisCapability = audioAnalysisCapability;
@@ -408730,6 +409419,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408730
409419
  exports.detectionPipelineCapability = detectionPipelineCapability;
408731
409420
  exports.deviceAdminLinkCapability = deviceAdminLinkCapability;
408732
409421
  exports.deviceAdoptionCapability = deviceAdoptionCapability;
409422
+ exports.deviceAttentionKind = deviceAttentionKind;
408733
409423
  exports.deviceBackendToFormat = deviceBackendToFormat;
408734
409424
  exports.deviceCredentialsCapability = deviceCredentialsCapability;
408735
409425
  exports.deviceCustomAction = require_sleep.deviceCustomAction;
@@ -408797,6 +409487,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408797
409487
  exports.expandAudioChunkToF32le = require_sleep.expandAudioChunkToF32le;
408798
409488
  exports.expandCapMethods = require_sleep.expandCapMethods;
408799
409489
  exports.expandContainer = expandContainer;
409490
+ exports.expandSystemEventClasses = expandSystemEventClasses;
408800
409491
  exports.exportSubjectOf = exportSubjectOf;
408801
409492
  exports.exposeBlockDevices = exposeBlockDevices;
408802
409493
  exports.expressionContainsBuiltinCall = expressionContainsBuiltinCall;
@@ -408938,6 +409629,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408938
409629
  exports.isStorageLocationMode = isStorageLocationMode;
408939
409630
  exports.isSystemDelivery = isSystemDelivery;
408940
409631
  exports.isSystemEventFamily = isSystemEventFamily;
409632
+ exports.isSystemEventRecoveryKind = isSystemEventRecoveryKind;
408941
409633
  exports.isSystemEventSummaryRule = isSystemEventSummaryRule;
408942
409634
  exports.isSystemRuleKind = isSystemRuleKind;
408943
409635
  exports.isVectorIndexDimConflict = isVectorIndexDimConflict;
@@ -409305,6 +409997,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
409305
409997
  exports.syncActiveAlarmProfileSettings = syncActiveAlarmProfileSettings;
409306
409998
  exports.synthesizeSourceInfo = synthesizeSourceInfo;
409307
409999
  exports.systemCapability = systemCapability;
410000
+ exports.systemEventClassKinds = systemEventClassKinds;
410001
+ exports.systemEventClassOf = systemEventClassOf;
410002
+ exports.systemEventClassesFor = systemEventClassesFor;
409308
410003
  exports.systemEventDeliveryProblems = systemEventDeliveryProblems;
409309
410004
  exports.systemEventFamilyOf = systemEventFamilyOf;
409310
410005
  exports.systemEventFamilyProblems = systemEventFamilyProblems;
@@ -409382,6 +410077,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
409382
410077
  exports.wiringProbeResultSchema = wiringProbeResultSchema;
409383
410078
  exports.withFieldFrom = withFieldFrom;
409384
410079
  exports.withLocationMode = withLocationMode;
410080
+ exports.withSystemEventClasses = withSystemEventClasses;
409385
410081
  exports.withoutCallerStamp = require_sleep.withoutCallerStamp;
409386
410082
  exports.withoutField = withoutField;
409387
410083
  exports.writeModelBoundSetting = writeModelBoundSetting;
@@ -589360,6 +590056,7 @@ var require_addon_registry_service = __commonJS({
589360
590056
  histogram: (input) => provider().histogram(as(input)),
589361
590057
  aggregate: (input) => provider().aggregate(as(input)),
589362
590058
  deleteWhere: (input) => provider().deleteWhere(as(input)),
590059
+ transact: (input) => provider().transact(as(input)),
589363
590060
  deleteDevice: (input) => provider().deleteDevice(as(input)),
589364
590061
  allocateId: (input) => provider().allocateId(as(input))
589365
590062
  };