camstack 1.2.143 → 1.2.145

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.
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-DdRxWA7g.js
23637
- var require_dist_DdRxWA7g = __commonJS({
23638
- "../system/dist/dist-DdRxWA7g.js"(exports) {
23636
+ // ../system/dist/dist-B84YlKAH.js
23637
+ var require_dist_B84YlKAH = __commonJS({
23638
+ "../system/dist/dist-B84YlKAH.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -25845,6 +25845,13 @@ var require_dist_DdRxWA7g = __commonJS({
25845
25845
  if (typeof err === "string") return err;
25846
25846
  return String(err);
25847
25847
  }
25848
+ var EVENT_OWNER_TYPES = [
25849
+ "motion",
25850
+ "object",
25851
+ "audio"
25852
+ ];
25853
+ var EventOwnerTypeSchema = zod.z.enum(EVENT_OWNER_TYPES);
25854
+ new Set(EVENT_OWNER_TYPES);
25848
25855
  var VideoEncodeSchema = zod.z.object({
25849
25856
  codec: zod.z.enum([
25850
25857
  "h264",
@@ -30739,6 +30746,60 @@ var require_dist_DdRxWA7g = __commonJS({
30739
30746
  filter: QueryFilterSchema.optional(),
30740
30747
  columns: zod.z.array(zod.z.string()).readonly().optional()
30741
30748
  }), zod.z.array(SettingsRecordSchema).readonly()),
30749
+ /**
30750
+ * Make a SLOT hold this row — insert it, or update whatever already
30751
+ * occupies the slot — and answer with the id the row HAS.
30752
+ *
30753
+ * ## Why the store needed this
30754
+ *
30755
+ * {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
30756
+ * caller has to know the id to address the row. That is exactly what a
30757
+ * collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
30758
+ * the id, so a writer whose uniqueness rule is "one row per
30759
+ * `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
30760
+ * express the rule. {@link insert} can express it (a UNIQUE index
30761
+ * arbitrates) but only by THROWING at the loser of a race, and the loser
30762
+ * here is a legitimate re-capture, not an error.
30763
+ *
30764
+ * Getting there without this method means read-then-write: query the slot,
30765
+ * then `insert` or `update`. Two statements instead of one, a race between
30766
+ * them, and a recovery path that has to recognise a UNIQUE violation by its
30767
+ * MESSAGE — across a process boundary, because the store lives behind an
30768
+ * RPC door. A string match would be the whole gate, and a store that
30769
+ * rephrased its error would lose the row silently. One statement has no
30770
+ * such gate (D482).
30771
+ *
30772
+ * ## The contract
30773
+ *
30774
+ * `conflict` names the DECLARED columns that identify the slot. They must
30775
+ * be covered by a UNIQUE index on the collection — SQLite resolves an
30776
+ * `ON CONFLICT` target against its indexes and REFUSES the statement when
30777
+ * none matches, so a wrong list is a loud error on the first write, never a
30778
+ * silently duplicated row. An empty list is refused rather than passed on:
30779
+ * `ON CONFLICT()` is not valid SQL, and the intent it would most likely
30780
+ * encode ("no slot, just insert") is {@link insert}.
30781
+ *
30782
+ * Row shape is {@link insert}'s: `record.id` is used when the collection
30783
+ * needs a supplied key and IGNORED when the primary key is an `INTEGER`
30784
+ * rowid alias — exactly as `insert` and `insertMany` already treat it.
30785
+ *
30786
+ * Returns the id either way: the one SQLite assigned on an insert, or the
30787
+ * one the row it updated already had. A caller cannot tell which happened,
30788
+ * and deliberately — every caller wants the slot's id, and one that needed
30789
+ * to distinguish creation from replacement would have to read first anyway.
30790
+ */
30791
+ upsert: method(zod.z.object({
30792
+ namespace: zod.z.string().optional(),
30793
+ collection: zod.z.string(),
30794
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
30795
+ * index on the collection. Never empty. */
30796
+ conflict: zod.z.array(zod.z.string()).readonly(),
30797
+ record: BulkRecordSchema
30798
+ }), zod.z.object({
30799
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
30800
+ * row's own id on an update. */
30801
+ id: zod.z.union([zod.z.string(), zod.z.number()])
30802
+ }), { kind: "mutation" }),
30742
30803
  /** Insert a new record. */
30743
30804
  insert: method(zod.z.object({
30744
30805
  namespace: zod.z.string().optional(),
@@ -30982,6 +31043,20 @@ var require_dist_DdRxWA7g = __commonJS({
30982
31043
  kind: "mutation",
30983
31044
  auth: "admin"
30984
31045
  }),
31046
+ /**
31047
+ * Make a slot hold this row, and answer with the id the row HAS. The
31048
+ * engine half of `settings-store.upsert` — read that docblock for why the
31049
+ * store needed a slot that is not the primary key (D482).
31050
+ */
31051
+ upsert: method(zod.z.object({
31052
+ namespace: zod.z.string().optional(),
31053
+ collection: zod.z.string(),
31054
+ conflict: zod.z.array(zod.z.string()).readonly(),
31055
+ record: BulkRecordSchema
31056
+ }), zod.z.object({ id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
31057
+ kind: "mutation",
31058
+ auth: "admin"
31059
+ }),
30985
31060
  /** Insert many records in ONE transaction. All or nothing. */
30986
31061
  insertMany: method(zod.z.object({
30987
31062
  namespace: zod.z.string().optional(),
@@ -37311,8 +37386,8 @@ var require_dist_DdRxWA7g = __commonJS({
37311
37386
  var TrackSnapshotSchema = zod.z.object({
37312
37387
  timestamp: zod.z.number(),
37313
37388
  position: TrackPositionSchema,
37314
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
37315
- mediaKey: zod.z.string()
37389
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
37390
+ mediaId: zod.z.number().int()
37316
37391
  });
37317
37392
  var TrackEnvelopeSchema = zod.z.object({
37318
37393
  minX: zod.z.number(),
@@ -37751,14 +37826,14 @@ var require_dist_DdRxWA7g = __commonJS({
37751
37826
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
37752
37827
  frameWidth: zod.z.number().optional(),
37753
37828
  frameHeight: zod.z.number().optional(),
37754
- /** MediaStore key for the crop attached to this event (if any). */
37755
- mediaKey: zod.z.string().optional(),
37756
- /** Design B: MediaStore key of the track's native-resolution key frame (the
37829
+ /** Media row id of the crop attached to this event (if any) — D482. */
37830
+ mediaId: zod.z.number().int().optional(),
37831
+ /** Design B: media row id of the track's native-resolution key frame (the
37757
37832
  * best-detection full frame). Resolve via the event-media data-plane
37758
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
37833
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
37759
37834
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
37760
- * sources — consumers fall back to `mediaKey` (the tight crop). */
37761
- keyFrameMediaKey: zod.z.string().optional(),
37835
+ * sources — consumers fall back to `mediaId` (the tight crop). */
37836
+ keyFrameMediaId: zod.z.number().int().optional(),
37762
37837
  /** Populated by B5 (recording playback URL for this event). */
37763
37838
  mediaUrl: zod.z.string().optional(),
37764
37839
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -37795,7 +37870,19 @@ var require_dist_DdRxWA7g = __commonJS({
37795
37870
  "sceneFrame"
37796
37871
  ]);
37797
37872
  var MediaFileSchema = zod.z.object({
37798
- key: zod.z.string(),
37873
+ /**
37874
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
37875
+ *
37876
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
37877
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
37878
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
37879
+ * different rows that spell the same number, and a track whose
37880
+ * `bestEventId` was an object event was served a motion event's snapshot —
37881
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
37882
+ * surrogate id cannot name the wrong row's owner, because it names no owner
37883
+ * at all.
37884
+ */
37885
+ mediaId: zod.z.number().int(),
37799
37886
  kind: MediaFileKindEnum,
37800
37887
  sizeBytes: zod.z.number(),
37801
37888
  timestamp: zod.z.number()
@@ -37862,7 +37949,7 @@ var require_dist_DdRxWA7g = __commonJS({
37862
37949
  annotationCount: zod.z.number().int()
37863
37950
  });
37864
37951
  var RetrainFrameCandidateSchema = zod.z.object({
37865
- mediaKey: zod.z.string(),
37952
+ mediaId: zod.z.number().int(),
37866
37953
  kind: MediaFileKindEnum,
37867
37954
  timestamp: zod.z.number(),
37868
37955
  sizeBytes: zod.z.number().int(),
@@ -37875,7 +37962,7 @@ var require_dist_DdRxWA7g = __commonJS({
37875
37962
  deviceId: zod.z.number(),
37876
37963
  trackId: zod.z.string(),
37877
37964
  /** Provenance only. It may already point at nothing — that is expected. */
37878
- sourceMediaKey: zod.z.string(),
37965
+ sourceMediaId: zod.z.number().int(),
37879
37966
  sourceKind: MediaFileKindEnum,
37880
37967
  sizeBytes: zod.z.number().int(),
37881
37968
  width: zod.z.number().int(),
@@ -37890,7 +37977,7 @@ var require_dist_DdRxWA7g = __commonJS({
37890
37977
  var RetrainFrameSelectionSchema = zod.z.object({
37891
37978
  copied: zod.z.array(RetrainFrameSchema).readonly(),
37892
37979
  refused: zod.z.array(zod.z.object({
37893
- sourceMediaKey: zod.z.string(),
37980
+ sourceMediaId: zod.z.number().int(),
37894
37981
  reason: RetrainCopyRefusalSchema
37895
37982
  })).readonly()
37896
37983
  });
@@ -37898,7 +37985,7 @@ var require_dist_DdRxWA7g = __commonJS({
37898
37985
  candidates: zod.z.array(RetrainFrameCandidateSchema).readonly(),
37899
37986
  copies: zod.z.array(RetrainFrameSchema).readonly(),
37900
37987
  /** What the page pre-selects — the native key frame when one survives. */
37901
- autoPickMediaKey: zod.z.string().optional()
37988
+ autoPickMediaId: zod.z.number().int().optional()
37902
37989
  });
37903
37990
  var RetrainAssistSubjectSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
37904
37991
  kind: zod.z.literal("package"),
@@ -37991,7 +38078,7 @@ var require_dist_DdRxWA7g = __commonJS({
37991
38078
  lastActiveAt: zod.z.number(),
37992
38079
  sealedAt: zod.z.number().nullable(),
37993
38080
  memberCount: zod.z.number().int().nonnegative(),
37994
- groupShotKey: zod.z.string().nullable()
38081
+ groupShotMediaId: zod.z.number().int().nullable()
37995
38082
  });
37996
38083
  var SummariesQueryInput = zod.z.object({
37997
38084
  deviceIds: zod.z.array(zod.z.number()).min(1),
@@ -38884,7 +38971,7 @@ var require_dist_DdRxWA7g = __commonJS({
38884
38971
  selectRetrainFrames: method(zod.z.object({
38885
38972
  deviceId: zod.z.number(),
38886
38973
  trackId: zod.z.string(),
38887
- mediaKeys: zod.z.array(zod.z.string()).min(1)
38974
+ mediaIds: zod.z.array(zod.z.number().int()).min(1)
38888
38975
  }), RetrainFrameSelectionSchema, {
38889
38976
  kind: "mutation",
38890
38977
  auth: "admin"
@@ -39048,8 +39135,29 @@ var require_dist_DdRxWA7g = __commonJS({
39048
39135
  kind: "query",
39049
39136
  auth: "admin"
39050
39137
  }),
39138
+ /**
39139
+ * The media an EVENT owns.
39140
+ *
39141
+ * `ownerType` is REQUIRED, and that is the whole correction (D482). An
39142
+ * event is a row in ONE of three tables, and since D474 each numbers from
39143
+ * 1 independently: `motion:101314` and `object:101314` both exist. This
39144
+ * method took a bare `eventId` and the provider probed motion → object →
39145
+ * audio, stopping at the first hit — so on the live hub, where object
39146
+ * events own no media of their own and 299 883 of 300 559 media rows are
39147
+ * motion-owned, EVERY object event resolved to its motion namesake. A
39148
+ * track from 17:34 on camera 615 was served a snapshot from 22:35 eleven
39149
+ * days earlier, silently.
39150
+ *
39151
+ * D476 had already disambiguated the KEY (`motion:` vs `object:`); this is
39152
+ * the API catching up to it. Naming the table is not a "qualification" of
39153
+ * the ambiguity — a listing BY OWNER has no address to make surrogate: the
39154
+ * owner IS (table, id), and half of it is not a question.
39155
+ */
39051
39156
  getEventMedia: method(zod.z.object({
39052
- eventId: zod.z.string(),
39157
+ /** Which of the three event tables owns the row. */
39158
+ ownerType: EventOwnerTypeSchema,
39159
+ /** The event's rowid in that table (D474: an event id is a number). */
39160
+ eventId: zod.z.number().int(),
39053
39161
  kind: MediaFileKindEnum.optional(),
39054
39162
  deviceId: zod.z.number()
39055
39163
  }), zod.z.array(MediaFileSchema).readonly()),
@@ -39094,11 +39202,14 @@ var require_dist_DdRxWA7g = __commonJS({
39094
39202
  * the live hub: one event's `fullFrameBoxed` is 2 824 077 B, base64'd to
39095
39203
  * ~3.8 MB, allocated whole in hub-main's heap, for a list of keys.
39096
39204
  *
39097
- * Same `deviceId` authorization subject as `getEventMedia`, and the same
39098
- * rows — this is a projection of that method, never a different question.
39205
+ * Same `deviceId` authorization subject as `getEventMedia`, the same
39206
+ * REQUIRED `ownerType` (read that method's docblock for the night-time
39207
+ * thumbnail this closes — D482), and the same rows: this is a projection
39208
+ * of that method, never a different question.
39099
39209
  */
39100
39210
  listEventMedia: method(zod.z.object({
39101
- eventId: zod.z.string(),
39211
+ ownerType: EventOwnerTypeSchema,
39212
+ eventId: zod.z.number().int(),
39102
39213
  deviceId: zod.z.number()
39103
39214
  }), zod.z.array(MediaFileInfoSchema).readonly()),
39104
39215
  /**
@@ -44602,8 +44713,8 @@ var require_dist_DdRxWA7g = __commonJS({
44602
44713
  id: zod.z.string(),
44603
44714
  name: zod.z.string(),
44604
44715
  sampleCount: zod.z.number().int().nonnegative(),
44605
- coverMediaKey: zod.z.string().optional(),
44606
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
44716
+ coverMediaId: zod.z.number().int().optional(),
44717
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
44607
44718
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
44608
44719
  coverBase64: zod.z.string().optional()
44609
44720
  });
@@ -44619,8 +44730,8 @@ var require_dist_DdRxWA7g = __commonJS({
44619
44730
  enrolledAt: zod.z.number().int(),
44620
44731
  deviceId: zod.z.number().int().optional(),
44621
44732
  source: zod.z.enum(["detected", "photo"]),
44622
- /** The enrolled crop's media key, so the panel can show the evidence. */
44623
- mediaKey: zod.z.string().optional(),
44733
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
44734
+ mediaId: zod.z.number().int().optional(),
44624
44735
  /**
44625
44736
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
44626
44737
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -44689,15 +44800,15 @@ var require_dist_DdRxWA7g = __commonJS({
44689
44800
  */
44690
44801
  cropUrl: zod.z.string().optional(),
44691
44802
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
44692
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
44803
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
44693
44804
  * legacy rows written before design B. */
44694
44805
  faceBbox: BoundingBoxSchema.optional(),
44695
44806
  /** Design B: MediaStore key of the track's native-resolution key frame.
44696
44807
  * Fetch the native JPEG via the event-media data-plane
44697
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
44808
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
44698
44809
  * track produced no key frame (e.g. native/onboard source) — the UI falls
44699
44810
  * back to the inline `base64` face crop. */
44700
- keyFrameMediaKey: zod.z.string().optional(),
44811
+ keyFrameMediaId: zod.z.number().int().optional(),
44701
44812
  /** Winning identity-match cosine (0..1) for this face's track, when an
44702
44813
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
44703
44814
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -44735,7 +44846,9 @@ var require_dist_DdRxWA7g = __commonJS({
44735
44846
  cohesion: zod.z.number()
44736
44847
  });
44737
44848
  var MediaFileLiteSchema$1 = zod.z.object({
44738
- key: zod.z.string(),
44849
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
44850
+ * (D482). It was the row's composite key, which embedded the owner. */
44851
+ mediaId: zod.z.number().int(),
44739
44852
  kind: zod.z.string(),
44740
44853
  url: zod.z.string(),
44741
44854
  sizeBytes: zod.z.number(),
@@ -44757,7 +44870,7 @@ var require_dist_DdRxWA7g = __commonJS({
44757
44870
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
44758
44871
  * four times and the viewer holds at `staleTime: 30_000`.
44759
44872
  *
44760
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
44873
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
44761
44874
  * the `event-media` plane serves that key `immutable` with an ETag.
44762
44875
  *
44763
44876
  * **This is an INPUT field, so it does not reach the addon until the
@@ -47885,8 +47998,8 @@ var require_dist_DdRxWA7g = __commonJS({
47885
47998
  id: zod.z.string(),
47886
47999
  name: zod.z.string(),
47887
48000
  sampleCount: zod.z.number().int().nonnegative(),
47888
- coverMediaKey: zod.z.string().optional(),
47889
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
48001
+ coverMediaId: zod.z.number().int().optional(),
48002
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
47890
48003
  coverBase64: zod.z.string().optional()
47891
48004
  });
47892
48005
  var VehicleSampleInfoSchema = zod.z.object({
@@ -47919,7 +48032,7 @@ var require_dist_DdRxWA7g = __commonJS({
47919
48032
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
47920
48033
  plateBbox: BoundingBoxSchema.optional(),
47921
48034
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
47922
- keyFrameMediaKey: zod.z.string().optional(),
48035
+ keyFrameMediaId: zod.z.number().int().optional(),
47923
48036
  base64: zod.z.string().optional(),
47924
48037
  /**
47925
48038
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -47930,7 +48043,9 @@ var require_dist_DdRxWA7g = __commonJS({
47930
48043
  cropUrl: zod.z.string().optional()
47931
48044
  });
47932
48045
  var MediaFileLiteSchema = zod.z.object({
47933
- key: zod.z.string(),
48046
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
48047
+ * (D482). It was the row's composite key, which embedded the owner. */
48048
+ mediaId: zod.z.number().int(),
47934
48049
  kind: zod.z.string(),
47935
48050
  url: zod.z.string(),
47936
48051
  sizeBytes: zod.z.number(),
@@ -48004,7 +48119,7 @@ var require_dist_DdRxWA7g = __commonJS({
48004
48119
  listVehicles: method(zod.z.object({
48005
48120
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
48006
48121
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
48007
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
48122
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
48008
48123
  * INPUT field: stripped by the hub router until the train ships, which
48009
48124
  * resolves to `false` and is exactly the intended default. */
48010
48125
  includeCrops: zod.z.boolean().optional()
@@ -49501,7 +49616,14 @@ var require_dist_DdRxWA7g = __commonJS({
49501
49616
  modelId: zod.z.string(),
49502
49617
  condition: SceneConditionSchema,
49503
49618
  capturedAt: zod.z.number(),
49504
- thumbnailMediaId: zod.z.string().optional(),
49619
+ /**
49620
+ * The reference thumbnail's media ROW id (D482).
49621
+ *
49622
+ * The name already said `mediaId` while the value was the row's composite
49623
+ * key — a leftover that read as done and was not. It is the row's own id
49624
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
49625
+ */
49626
+ thumbnailMediaId: zod.z.number().int().optional(),
49505
49627
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
49506
49628
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
49507
49629
  * normalized rect frame a different piece of world, and the scene would
@@ -51423,7 +51545,7 @@ var require_dist_DdRxWA7g = __commonJS({
51423
51545
  /** Enrichment label carried from the source track (identity / plate). */
51424
51546
  label: zod.z.string().optional(),
51425
51547
  /** Native-resolution key-frame media key for the parked object's best image. */
51426
- keyFrameMediaKey: zod.z.string().optional()
51548
+ keyFrameMediaId: zod.z.number().int().optional()
51427
51549
  });
51428
51550
  var CameraOccupancySnapshotSchema = zod.z.object({
51429
51551
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -53287,6 +53409,12 @@ var require_dist_DdRxWA7g = __commonJS({
53287
53409
  addonId: null,
53288
53410
  access: "create"
53289
53411
  },
53412
+ "dataStoreProvider.upsert": {
53413
+ capName: "data-store-provider",
53414
+ capScope: "system",
53415
+ addonId: null,
53416
+ access: "create"
53417
+ },
53290
53418
  "dayNight.getOptions": {
53291
53419
  capName: "day-night",
53292
53420
  capScope: "device",
@@ -57151,6 +57279,12 @@ var require_dist_DdRxWA7g = __commonJS({
57151
57279
  addonId: null,
57152
57280
  access: "create"
57153
57281
  },
57282
+ "settingsStore.upsert": {
57283
+ capName: "settings-store",
57284
+ capScope: "system",
57285
+ addonId: null,
57286
+ access: "create"
57287
+ },
57154
57288
  "smtpProvider.getStatus": {
57155
57289
  capName: "smtp-provider",
57156
57290
  capScope: "system",
@@ -61865,7 +61999,7 @@ var require_alerts_addon = __commonJS({
61865
61999
  [Symbol.toStringTag]: { value: "Module" }
61866
62000
  });
61867
62001
  require_chunk_Cek0wNdY();
61868
- var require_dist10 = require_dist_DdRxWA7g();
62002
+ var require_dist10 = require_dist_B84YlKAH();
61869
62003
  function selectExpired(alerts, cutoffMs) {
61870
62004
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
61871
62005
  }
@@ -62684,7 +62818,7 @@ var require_console_logging = __commonJS({
62684
62818
  [Symbol.toStringTag]: { value: "Module" }
62685
62819
  });
62686
62820
  require_chunk_Cek0wNdY();
62687
- var require_dist10 = require_dist_DdRxWA7g();
62821
+ var require_dist10 = require_dist_B84YlKAH();
62688
62822
  var require_formatter = require_formatter_DqAKDlvN();
62689
62823
  var LEVEL_RANK = {
62690
62824
  debug: 0,
@@ -62778,7 +62912,7 @@ var require_core_blocks_addon = __commonJS({
62778
62912
  "use strict";
62779
62913
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
62780
62914
  var require_chunk = require_chunk_Cek0wNdY();
62781
- var require_dist10 = require_dist_DdRxWA7g();
62915
+ var require_dist10 = require_dist_B84YlKAH();
62782
62916
  var node_crypto = __require("crypto");
62783
62917
  var node_fs_promises = __require("fs/promises");
62784
62918
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -63675,11 +63809,11 @@ var require_core_blocks = __commonJS({
63675
63809
  }
63676
63810
  });
63677
63811
 
63678
- // ../system/dist/retired-settings-keys-C-jOWHI0.js
63679
- var require_retired_settings_keys_C_jOWHI0 = __commonJS({
63680
- "../system/dist/retired-settings-keys-C-jOWHI0.js"(exports) {
63812
+ // ../system/dist/retired-settings-keys-Cxgwa0bk.js
63813
+ var require_retired_settings_keys_Cxgwa0bk = __commonJS({
63814
+ "../system/dist/retired-settings-keys-Cxgwa0bk.js"(exports) {
63681
63815
  "use strict";
63682
- var require_dist10 = require_dist_DdRxWA7g();
63816
+ var require_dist10 = require_dist_B84YlKAH();
63683
63817
  function settingsStoreIsAuthoritativeHere(env) {
63684
63818
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
63685
63819
  return raw === "" || raw === "hub";
@@ -65914,8 +66048,8 @@ var require_device_manager_addon = __commonJS({
65914
66048
  [Symbol.toStringTag]: { value: "Module" }
65915
66049
  });
65916
66050
  require_chunk_Cek0wNdY();
65917
- var require_dist10 = require_dist_DdRxWA7g();
65918
- var require_retired_settings_keys = require_retired_settings_keys_C_jOWHI0();
66051
+ var require_dist10 = require_dist_B84YlKAH();
66052
+ var require_retired_settings_keys = require_retired_settings_keys_Cxgwa0bk();
65919
66053
  var node_crypto = __require("crypto");
65920
66054
  var _camstack_types_node = require_node();
65921
66055
  var JOB_HISTORY = 20;
@@ -71540,7 +71674,7 @@ var require_hub_forwarder = __commonJS({
71540
71674
  [Symbol.toStringTag]: { value: "Module" }
71541
71675
  });
71542
71676
  require_chunk_Cek0wNdY();
71543
- var require_dist10 = require_dist_DdRxWA7g();
71677
+ var require_dist10 = require_dist_B84YlKAH();
71544
71678
  var require_formatter = require_formatter_DqAKDlvN();
71545
71679
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
71546
71680
  var HubForwarderDestination = class {
@@ -71677,7 +71811,7 @@ var require_liveness_monitor_addon = __commonJS({
71677
71811
  "use strict";
71678
71812
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
71679
71813
  require_chunk_Cek0wNdY();
71680
- var require_dist10 = require_dist_DdRxWA7g();
71814
+ var require_dist10 = require_dist_B84YlKAH();
71681
71815
  var NO_DEVICES = "liveness:no-devices";
71682
71816
  var ALL_OFFLINE = "liveness:all-devices-offline";
71683
71817
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -71873,7 +72007,7 @@ var require_local_auth_addon = __commonJS({
71873
72007
  [Symbol.toStringTag]: { value: "Module" }
71874
72008
  });
71875
72009
  var require_chunk = require_chunk_Cek0wNdY();
71876
- var require_dist10 = require_dist_DdRxWA7g();
72010
+ var require_dist10 = require_dist_B84YlKAH();
71877
72011
  var node_crypto = __require("crypto");
71878
72012
  node_crypto = require_chunk.__toESM(node_crypto);
71879
72013
  var crypto$1 = __require("crypto");
@@ -79686,7 +79820,7 @@ var require_loki_logging = __commonJS({
79686
79820
  [Symbol.toStringTag]: { value: "Module" }
79687
79821
  });
79688
79822
  require_chunk_Cek0wNdY();
79689
- var require_dist10 = require_dist_DdRxWA7g();
79823
+ var require_dist10 = require_dist_B84YlKAH();
79690
79824
  function sanitizeLabelName(raw) {
79691
79825
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
79692
79826
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -80273,7 +80407,7 @@ var require_native_metrics_addon = __commonJS({
80273
80407
  [Symbol.toStringTag]: { value: "Module" }
80274
80408
  });
80275
80409
  var require_chunk = require_chunk_Cek0wNdY();
80276
- var require_dist10 = require_dist_DdRxWA7g();
80410
+ var require_dist10 = require_dist_B84YlKAH();
80277
80411
  var node_fs_promises = __require("fs/promises");
80278
80412
  var node_fs = __require("fs");
80279
80413
  node_fs = require_chunk.__toESM(node_fs);
@@ -83026,7 +83160,7 @@ var require_filesystem_storage_addon = __commonJS({
83026
83160
  [Symbol.toStringTag]: { value: "Module" }
83027
83161
  });
83028
83162
  var require_chunk = require_chunk_Cek0wNdY();
83029
- var require_dist10 = require_dist_DdRxWA7g();
83163
+ var require_dist10 = require_dist_B84YlKAH();
83030
83164
  var node_crypto = __require("crypto");
83031
83165
  var node_fs_promises = __require("fs/promises");
83032
83166
  var node_path = __require("path");
@@ -84253,8 +84387,8 @@ var require_sqlite_settings_addon = __commonJS({
84253
84387
  [Symbol.toStringTag]: { value: "Module" }
84254
84388
  });
84255
84389
  var require_chunk = require_chunk_Cek0wNdY();
84256
- var require_dist10 = require_dist_DdRxWA7g();
84257
- var require_retired_settings_keys = require_retired_settings_keys_C_jOWHI0();
84390
+ var require_dist10 = require_dist_B84YlKAH();
84391
+ var require_retired_settings_keys = require_retired_settings_keys_Cxgwa0bk();
84258
84392
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
84259
84393
  var node_crypto = __require("crypto");
84260
84394
  var node_path = __require("path");
@@ -85082,6 +85216,54 @@ var require_sqlite_settings_addon = __commonJS({
85082
85216
  return { id: suppliedOrMinted ?? Number(rowid) };
85083
85217
  }
85084
85218
  /**
85219
+ * Make a SLOT hold this row, and answer with the id the row HAS — one
85220
+ * statement, `INSERT … ON CONFLICT(<slot>) DO UPDATE … RETURNING <pk>`.
85221
+ *
85222
+ * See `settings-store.cap.ts`'s `upsert` docblock for why the store needed a
85223
+ * slot that is not the primary key (D482). Three things are load-bearing
85224
+ * here:
85225
+ *
85226
+ * - **`RETURNING` and not `lastInsertRowid`.** On the UPDATE branch
85227
+ * `lastInsertRowid` is whatever the connection last inserted — a
85228
+ * different row, or a different TABLE. It answers confidently and wrongly,
85229
+ * which is worse than not answering. `RETURNING` names the row this
85230
+ * statement actually touched, on both branches.
85231
+ * - **The conflict columns are checked against the declaration** before they
85232
+ * reach the SQL. An undeclared name would be interpolated into DDL-shaped
85233
+ * text; it is refused, by the same rule and for the same reason
85234
+ * {@link resolveProjection} throws on an unprojectable column.
85235
+ * - **The primary key is never part of the SET list.** An `INTEGER` rowid
85236
+ * alias is not in `row` at all, and on a TEXT key rewriting the id of the
85237
+ * row we just matched is the one update that cannot be right.
85238
+ */
85239
+ async upsert({ namespace, collection, conflict, record }) {
85240
+ const scoped = this.scopedName(namespace, collection);
85241
+ const decl = this.requireDeclared(scoped);
85242
+ if (conflict.length === 0) throw new UnprojectableColumnError(`upsert on "${scoped}" was given an EMPTY conflict target \u2014 "ON CONFLICT()" is not valid SQL, and "no slot, just insert" is insert()`);
85243
+ const unknownCols = conflict.filter((name) => !decl.columns.has(name) && name !== decl.primaryKey);
85244
+ if (unknownCols.length > 0) throw new UnprojectableColumnError(`upsert on "${scoped}" names conflict column(s) the collection does not declare: ${unknownCols.join(", ")}`);
85245
+ const suppliedOrMinted = decl.autoPrimaryKey ? null : record.id || (0, node_crypto.randomUUID)();
85246
+ const row = decl.autoPrimaryKey ? {} : { [decl.primaryKey]: suppliedOrMinted };
85247
+ if (decl.columns.size === 1 && decl.columns.has("data")) row["data"] = JSON.stringify(record.data);
85248
+ else for (const [k, v] of Object.entries(record.data)) if (decl.columns.has(k)) row[k] = this.serializeColumnValue(v);
85249
+ const keys = Object.keys(row);
85250
+ const cols = keys.map((k) => `"${k}"`).join(", ");
85251
+ const placeholders = keys.map(() => "?").join(", ");
85252
+ const target = conflict.map((k) => `"${k}"`).join(", ");
85253
+ const updates = keys.filter((k) => k !== decl.primaryKey && !conflict.includes(k)).map((k) => `"${k}" = excluded."${k}"`);
85254
+ const sql = `INSERT INTO "${scoped}" (${cols}) VALUES (${placeholders}) ON CONFLICT(${target}) DO UPDATE SET ${updates.length > 0 ? updates.join(", ") : `"${conflict[0]}" = excluded."${conflict[0]}"`} RETURNING "${decl.primaryKey}"`;
85255
+ const values = keys.map((k) => row[k] ?? null);
85256
+ const id = this.measured({
85257
+ op: "upsert",
85258
+ collection: scoped,
85259
+ sql,
85260
+ params: values
85261
+ }, () => this.getDb().prepare(sql).get(...values))?.[decl.primaryKey];
85262
+ if (typeof id === "number" || typeof id === "bigint") return { id: Number(id) };
85263
+ if (typeof id === "string") return { id };
85264
+ throw new Error(`upsert on "${scoped}" returned no row \u2014 the ON CONFLICT target (${target}) resolved to no unique index, or the write was rejected`);
85265
+ }
85266
+ /**
85085
85267
  * Insert a batch in ONE transaction, on ONE prepared statement.
85086
85268
  *
85087
85269
  * The write-side twin of {@link deleteWhere}. Every row in the batch shares
@@ -86993,7 +87175,7 @@ var require_storage_orchestrator_addon = __commonJS({
86993
87175
  [Symbol.toStringTag]: { value: "Module" }
86994
87176
  });
86995
87177
  var require_chunk = require_chunk_Cek0wNdY();
86996
- var require_dist10 = require_dist_DdRxWA7g();
87178
+ var require_dist10 = require_dist_B84YlKAH();
86997
87179
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
86998
87180
  var zod = require_zod();
86999
87181
  var node_crypto = __require("crypto");
@@ -88030,6 +88212,7 @@ var require_storage_orchestrator_addon = __commonJS({
88030
88212
  set: async (input) => (await engine()).set(input),
88031
88213
  query: async (input) => (await engine()).query(input),
88032
88214
  insert: async (input) => (await engine()).insert(input),
88215
+ upsert: async (input) => (await engine()).upsert(input),
88033
88216
  insertMany: async (input) => (await engine()).insertMany(input),
88034
88217
  update: async (input) => (await engine()).update(input),
88035
88218
  delete: async (input) => (await engine()).delete(input),
@@ -88177,6 +88360,7 @@ var require_storage_orchestrator_addon = __commonJS({
88177
88360
  set: (input) => send("set", input),
88178
88361
  query: (input) => send("query", input),
88179
88362
  insert: (input) => send("insert", input),
88363
+ upsert: (input) => send("upsert", input),
88180
88364
  insertMany: (input) => send("insertMany", input),
88181
88365
  update: (input) => send("update", input),
88182
88366
  delete: (input) => send("delete", input),
@@ -90643,7 +90827,7 @@ var require_system_config_addon = __commonJS({
90643
90827
  [Symbol.toStringTag]: { value: "Module" }
90644
90828
  });
90645
90829
  require_chunk_Cek0wNdY();
90646
- var require_dist10 = require_dist_DdRxWA7g();
90830
+ var require_dist10 = require_dist_B84YlKAH();
90647
90831
  var SECTION_TITLES = {
90648
90832
  server: "Server",
90649
90833
  auth: "Authentication"
@@ -108704,7 +108888,7 @@ var require_winston_logging = __commonJS({
108704
108888
  [Symbol.toStringTag]: { value: "Module" }
108705
108889
  });
108706
108890
  var require_chunk = require_chunk_Cek0wNdY();
108707
- var require_dist10 = require_dist_DdRxWA7g();
108891
+ var require_dist10 = require_dist_B84YlKAH();
108708
108892
  var require_formatter = require_formatter_DqAKDlvN();
108709
108893
  var node_path = __require("path");
108710
108894
  node_path = require_chunk.__toESM(node_path);
@@ -110573,9 +110757,9 @@ ${(0, node_fs.readFileSync)(ca.caCertPath, "utf-8").trimEnd()}
110573
110757
  }
110574
110758
  });
110575
110759
 
110576
- // ../types/dist/event-category-BNJ9EE5B.js
110577
- var require_event_category_BNJ9EE5B = __commonJS({
110578
- "../types/dist/event-category-BNJ9EE5B.js"(exports) {
110760
+ // ../types/dist/event-category-yW4s1MGD.js
110761
+ var require_event_category_yW4s1MGD = __commonJS({
110762
+ "../types/dist/event-category-yW4s1MGD.js"(exports) {
110579
110763
  "use strict";
110580
110764
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
110581
110765
  EventCategory2["SystemBoot"] = "system.boot";
@@ -110741,11 +110925,11 @@ var require_event_category_BNJ9EE5B = __commonJS({
110741
110925
  }
110742
110926
  });
110743
110927
 
110744
- // ../types/dist/sleep-B1ZwxAhh.js
110745
- var require_sleep_B1ZwxAhh = __commonJS({
110746
- "../types/dist/sleep-B1ZwxAhh.js"(exports) {
110928
+ // ../types/dist/sleep-CfDqEZrs.js
110929
+ var require_sleep_CfDqEZrs = __commonJS({
110930
+ "../types/dist/sleep-CfDqEZrs.js"(exports) {
110747
110931
  "use strict";
110748
- var require_event_category = require_event_category_BNJ9EE5B();
110932
+ var require_event_category = require_event_category_yW4s1MGD();
110749
110933
  var zod = require_zod();
110750
110934
  var AUDIO_CHUNK_FORMATS = [
110751
110935
  "f32le",
@@ -114575,8 +114759,8 @@ var require_addon = __commonJS({
114575
114759
  "../types/dist/addon.js"(exports) {
114576
114760
  "use strict";
114577
114761
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
114578
- var require_sleep = require_sleep_B1ZwxAhh();
114579
- var require_event_category = require_event_category_BNJ9EE5B();
114762
+ var require_sleep = require_sleep_CfDqEZrs();
114763
+ var require_event_category = require_event_category_yW4s1MGD();
114580
114764
  var require_err_msg = require_err_msg_COpsHMw2();
114581
114765
  var CAP_INPUT_DEFAULTS = Object.freeze({
114582
114766
  "addons": { "getLogs": { "limit": 100 } },
@@ -130964,11 +131148,11 @@ var require_manifest_system_deps_8x1jgPz = __commonJS({
130964
131148
  }
130965
131149
  });
130966
131150
 
130967
- // ../system/dist/custom-action-registry-BTB-LgGN.js
130968
- var require_custom_action_registry_BTB_LgGN = __commonJS({
130969
- "../system/dist/custom-action-registry-BTB-LgGN.js"(exports) {
131151
+ // ../system/dist/custom-action-registry-DwaSEiji.js
131152
+ var require_custom_action_registry_DwaSEiji = __commonJS({
131153
+ "../system/dist/custom-action-registry-DwaSEiji.js"(exports) {
130970
131154
  "use strict";
130971
- var require_dist10 = require_dist_DdRxWA7g();
131155
+ var require_dist10 = require_dist_B84YlKAH();
130972
131156
  var CustomActionRegistry = class {
130973
131157
  byAddon = /* @__PURE__ */ new Map();
130974
131158
  registerAddon(addonId, catalog, handler) {
@@ -134782,7 +134966,7 @@ var require_dist3 = __commonJS({
134782
134966
  "use strict";
134783
134967
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
134784
134968
  var require_chunk = require_chunk_Cek0wNdY();
134785
- var require_dist10 = require_dist_DdRxWA7g();
134969
+ var require_dist10 = require_dist_B84YlKAH();
134786
134970
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
134787
134971
  require_alerts();
134788
134972
  var require_formatter = require_formatter_DqAKDlvN();
@@ -134811,7 +134995,7 @@ var require_dist3 = __commonJS({
134811
134995
  var require_tls$1 = require_tls_BFs4PzoW();
134812
134996
  var require_manifest_system_deps = require_manifest_system_deps_8x1jgPz();
134813
134997
  var require_resource_monitor = require_resource_monitor_LVE1BoLs();
134814
- var require_custom_action_registry = require_custom_action_registry_BTB_LgGN();
134998
+ var require_custom_action_registry = require_custom_action_registry_DwaSEiji();
134815
134999
  var zod = require_zod();
134816
135000
  var node_crypto = __require("crypto");
134817
135001
  var _camstack_types_node = require_node();
@@ -215899,7 +216083,7 @@ var require_enums = __commonJS({
215899
216083
  "../types/dist/enums.js"(exports) {
215900
216084
  "use strict";
215901
216085
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
215902
- var require_event_category = require_event_category_BNJ9EE5B();
216086
+ var require_event_category = require_event_category_yW4s1MGD();
215903
216087
  var EventSourceType = /* @__PURE__ */ (function(EventSourceType2) {
215904
216088
  EventSourceType2["Addon"] = "addon";
215905
216089
  EventSourceType2["Core"] = "core";
@@ -215919,8 +216103,8 @@ var require_dist4 = __commonJS({
215919
216103
  "../types/dist/index.js"(exports) {
215920
216104
  "use strict";
215921
216105
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
215922
- var require_sleep = require_sleep_B1ZwxAhh();
215923
- var require_event_category = require_event_category_BNJ9EE5B();
216106
+ var require_sleep = require_sleep_CfDqEZrs();
216107
+ var require_event_category = require_event_category_yW4s1MGD();
215924
216108
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
215925
216109
  var require_enums2 = require_enums();
215926
216110
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -215935,18 +216119,19 @@ var require_dist4 = __commonJS({
215935
216119
  "scene",
215936
216120
  "motion",
215937
216121
  "object",
215938
- "audio"
216122
+ "audio",
216123
+ "mosaic"
215939
216124
  ];
215940
216125
  var OWNER_TYPES = new Set(MEDIA_OWNER_TYPES);
215941
216126
  var DIGITS = /^\d+$/;
215942
- function isOwnerType(value) {
216127
+ function isMediaOwnerType(value) {
215943
216128
  return OWNER_TYPES.has(value);
215944
216129
  }
215945
216130
  function parseMediaOwnerKey(key) {
215946
216131
  const parts = key.split(":");
215947
216132
  if (parts.length !== 3 && parts.length !== 4) return null;
215948
216133
  const [ownerType, ownerId, fileKind, timestamp] = parts;
215949
- if (ownerType === void 0 || !isOwnerType(ownerType)) return null;
216134
+ if (ownerType === void 0 || !isMediaOwnerType(ownerType)) return null;
215950
216135
  if (ownerId === void 0 || ownerId.length === 0) return null;
215951
216136
  if (fileKind === void 0 || fileKind.length === 0) return null;
215952
216137
  if (timestamp === void 0) return {
@@ -215971,6 +216156,7 @@ var require_dist4 = __commonJS({
215971
216156
  "object",
215972
216157
  "audio"
215973
216158
  ];
216159
+ var EventOwnerTypeSchema = zod.z.enum(EVENT_OWNER_TYPES);
215974
216160
  var EVENT_OWNER_TYPE_SET = new Set(EVENT_OWNER_TYPES);
215975
216161
  function isEventOwnerType(ownerType) {
215976
216162
  return EVENT_OWNER_TYPE_SET.has(ownerType);
@@ -222875,6 +223061,60 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
222875
223061
  filter: QueryFilterSchema.optional(),
222876
223062
  columns: zod.z.array(zod.z.string()).readonly().optional()
222877
223063
  }), zod.z.array(SettingsRecordSchema).readonly()),
223064
+ /**
223065
+ * Make a SLOT hold this row — insert it, or update whatever already
223066
+ * occupies the slot — and answer with the id the row HAS.
223067
+ *
223068
+ * ## Why the store needed this
223069
+ *
223070
+ * {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
223071
+ * caller has to know the id to address the row. That is exactly what a
223072
+ * collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
223073
+ * the id, so a writer whose uniqueness rule is "one row per
223074
+ * `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
223075
+ * express the rule. {@link insert} can express it (a UNIQUE index
223076
+ * arbitrates) but only by THROWING at the loser of a race, and the loser
223077
+ * here is a legitimate re-capture, not an error.
223078
+ *
223079
+ * Getting there without this method means read-then-write: query the slot,
223080
+ * then `insert` or `update`. Two statements instead of one, a race between
223081
+ * them, and a recovery path that has to recognise a UNIQUE violation by its
223082
+ * MESSAGE — across a process boundary, because the store lives behind an
223083
+ * RPC door. A string match would be the whole gate, and a store that
223084
+ * rephrased its error would lose the row silently. One statement has no
223085
+ * such gate (D482).
223086
+ *
223087
+ * ## The contract
223088
+ *
223089
+ * `conflict` names the DECLARED columns that identify the slot. They must
223090
+ * be covered by a UNIQUE index on the collection — SQLite resolves an
223091
+ * `ON CONFLICT` target against its indexes and REFUSES the statement when
223092
+ * none matches, so a wrong list is a loud error on the first write, never a
223093
+ * silently duplicated row. An empty list is refused rather than passed on:
223094
+ * `ON CONFLICT()` is not valid SQL, and the intent it would most likely
223095
+ * encode ("no slot, just insert") is {@link insert}.
223096
+ *
223097
+ * Row shape is {@link insert}'s: `record.id` is used when the collection
223098
+ * needs a supplied key and IGNORED when the primary key is an `INTEGER`
223099
+ * rowid alias — exactly as `insert` and `insertMany` already treat it.
223100
+ *
223101
+ * Returns the id either way: the one SQLite assigned on an insert, or the
223102
+ * one the row it updated already had. A caller cannot tell which happened,
223103
+ * and deliberately — every caller wants the slot's id, and one that needed
223104
+ * to distinguish creation from replacement would have to read first anyway.
223105
+ */
223106
+ upsert: require_sleep.method(zod.z.object({
223107
+ namespace: zod.z.string().optional(),
223108
+ collection: zod.z.string(),
223109
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
223110
+ * index on the collection. Never empty. */
223111
+ conflict: zod.z.array(zod.z.string()).readonly(),
223112
+ record: BulkRecordSchema
223113
+ }), zod.z.object({
223114
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
223115
+ * row's own id on an update. */
223116
+ id: zod.z.union([zod.z.string(), zod.z.number()])
223117
+ }), { kind: "mutation" }),
222878
223118
  /** Insert a new record. */
222879
223119
  insert: require_sleep.method(zod.z.object({
222880
223120
  namespace: zod.z.string().optional(),
@@ -223118,6 +223358,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
223118
223358
  kind: "mutation",
223119
223359
  auth: "admin"
223120
223360
  }),
223361
+ /**
223362
+ * Make a slot hold this row, and answer with the id the row HAS. The
223363
+ * engine half of `settings-store.upsert` — read that docblock for why the
223364
+ * store needed a slot that is not the primary key (D482).
223365
+ */
223366
+ upsert: require_sleep.method(zod.z.object({
223367
+ namespace: zod.z.string().optional(),
223368
+ collection: zod.z.string(),
223369
+ conflict: zod.z.array(zod.z.string()).readonly(),
223370
+ record: BulkRecordSchema
223371
+ }), zod.z.object({ id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
223372
+ kind: "mutation",
223373
+ auth: "admin"
223374
+ }),
223121
223375
  /** Insert many records in ONE transaction. All or nothing. */
223122
223376
  insertMany: require_sleep.method(zod.z.object({
223123
223377
  namespace: zod.z.string().optional(),
@@ -230347,8 +230601,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230347
230601
  var TrackSnapshotSchema = zod.z.object({
230348
230602
  timestamp: zod.z.number(),
230349
230603
  position: TrackPositionSchema,
230350
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
230351
- mediaKey: zod.z.string()
230604
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
230605
+ mediaId: zod.z.number().int()
230352
230606
  });
230353
230607
  var TrackEnvelopeSchema = zod.z.object({
230354
230608
  minX: zod.z.number(),
@@ -230788,14 +231042,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230788
231042
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
230789
231043
  frameWidth: zod.z.number().optional(),
230790
231044
  frameHeight: zod.z.number().optional(),
230791
- /** MediaStore key for the crop attached to this event (if any). */
230792
- mediaKey: zod.z.string().optional(),
230793
- /** Design B: MediaStore key of the track's native-resolution key frame (the
231045
+ /** Media row id of the crop attached to this event (if any) — D482. */
231046
+ mediaId: zod.z.number().int().optional(),
231047
+ /** Design B: media row id of the track's native-resolution key frame (the
230794
231048
  * best-detection full frame). Resolve via the event-media data-plane
230795
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
231049
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
230796
231050
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
230797
- * sources — consumers fall back to `mediaKey` (the tight crop). */
230798
- keyFrameMediaKey: zod.z.string().optional(),
231051
+ * sources — consumers fall back to `mediaId` (the tight crop). */
231052
+ keyFrameMediaId: zod.z.number().int().optional(),
230799
231053
  /** Populated by B5 (recording playback URL for this event). */
230800
231054
  mediaUrl: zod.z.string().optional(),
230801
231055
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -230832,7 +231086,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230832
231086
  "sceneFrame"
230833
231087
  ]);
230834
231088
  var MediaFileRefSchema = zod.z.object({
230835
- key: zod.z.string(),
231089
+ /**
231090
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
231091
+ *
231092
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
231093
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
231094
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
231095
+ * different rows that spell the same number, and a track whose
231096
+ * `bestEventId` was an object event was served a motion event's snapshot —
231097
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
231098
+ * surrogate id cannot name the wrong row's owner, because it names no owner
231099
+ * at all.
231100
+ */
231101
+ mediaId: zod.z.number().int(),
230836
231102
  kind: MediaFileKindEnum,
230837
231103
  sizeBytes: zod.z.number(),
230838
231104
  timestamp: zod.z.number()
@@ -230900,7 +231166,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230900
231166
  annotationCount: zod.z.number().int()
230901
231167
  });
230902
231168
  var RetrainFrameCandidateSchema = zod.z.object({
230903
- mediaKey: zod.z.string(),
231169
+ mediaId: zod.z.number().int(),
230904
231170
  kind: MediaFileKindEnum,
230905
231171
  timestamp: zod.z.number(),
230906
231172
  sizeBytes: zod.z.number().int(),
@@ -230913,7 +231179,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230913
231179
  deviceId: zod.z.number(),
230914
231180
  trackId: zod.z.string(),
230915
231181
  /** Provenance only. It may already point at nothing — that is expected. */
230916
- sourceMediaKey: zod.z.string(),
231182
+ sourceMediaId: zod.z.number().int(),
230917
231183
  sourceKind: MediaFileKindEnum,
230918
231184
  sizeBytes: zod.z.number().int(),
230919
231185
  width: zod.z.number().int(),
@@ -230928,7 +231194,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230928
231194
  var RetrainFrameSelectionSchema = zod.z.object({
230929
231195
  copied: zod.z.array(RetrainFrameSchema).readonly(),
230930
231196
  refused: zod.z.array(zod.z.object({
230931
- sourceMediaKey: zod.z.string(),
231197
+ sourceMediaId: zod.z.number().int(),
230932
231198
  reason: RetrainCopyRefusalSchema
230933
231199
  })).readonly()
230934
231200
  });
@@ -230936,7 +231202,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230936
231202
  candidates: zod.z.array(RetrainFrameCandidateSchema).readonly(),
230937
231203
  copies: zod.z.array(RetrainFrameSchema).readonly(),
230938
231204
  /** What the page pre-selects — the native key frame when one survives. */
230939
- autoPickMediaKey: zod.z.string().optional()
231205
+ autoPickMediaId: zod.z.number().int().optional()
230940
231206
  });
230941
231207
  var RetrainAssistSubjectSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
230942
231208
  kind: zod.z.literal("package"),
@@ -231029,7 +231295,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
231029
231295
  lastActiveAt: zod.z.number(),
231030
231296
  sealedAt: zod.z.number().nullable(),
231031
231297
  memberCount: zod.z.number().int().nonnegative(),
231032
- groupShotKey: zod.z.string().nullable()
231298
+ groupShotMediaId: zod.z.number().int().nullable()
231033
231299
  });
231034
231300
  var SUMMARIES_MAX_LIMIT = 200;
231035
231301
  var SUMMARIES_DEFAULT_LIMIT = 50;
@@ -231925,7 +232191,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
231925
232191
  selectRetrainFrames: require_sleep.method(zod.z.object({
231926
232192
  deviceId: zod.z.number(),
231927
232193
  trackId: zod.z.string(),
231928
- mediaKeys: zod.z.array(zod.z.string()).min(1)
232194
+ mediaIds: zod.z.array(zod.z.number().int()).min(1)
231929
232195
  }), RetrainFrameSelectionSchema, {
231930
232196
  kind: "mutation",
231931
232197
  auth: "admin"
@@ -232089,8 +232355,29 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
232089
232355
  kind: "query",
232090
232356
  auth: "admin"
232091
232357
  }),
232358
+ /**
232359
+ * The media an EVENT owns.
232360
+ *
232361
+ * `ownerType` is REQUIRED, and that is the whole correction (D482). An
232362
+ * event is a row in ONE of three tables, and since D474 each numbers from
232363
+ * 1 independently: `motion:101314` and `object:101314` both exist. This
232364
+ * method took a bare `eventId` and the provider probed motion → object →
232365
+ * audio, stopping at the first hit — so on the live hub, where object
232366
+ * events own no media of their own and 299 883 of 300 559 media rows are
232367
+ * motion-owned, EVERY object event resolved to its motion namesake. A
232368
+ * track from 17:34 on camera 615 was served a snapshot from 22:35 eleven
232369
+ * days earlier, silently.
232370
+ *
232371
+ * D476 had already disambiguated the KEY (`motion:` vs `object:`); this is
232372
+ * the API catching up to it. Naming the table is not a "qualification" of
232373
+ * the ambiguity — a listing BY OWNER has no address to make surrogate: the
232374
+ * owner IS (table, id), and half of it is not a question.
232375
+ */
232092
232376
  getEventMedia: require_sleep.method(zod.z.object({
232093
- eventId: zod.z.string(),
232377
+ /** Which of the three event tables owns the row. */
232378
+ ownerType: EventOwnerTypeSchema,
232379
+ /** The event's rowid in that table (D474: an event id is a number). */
232380
+ eventId: zod.z.number().int(),
232094
232381
  kind: MediaFileKindEnum.optional(),
232095
232382
  deviceId: zod.z.number()
232096
232383
  }), zod.z.array(MediaFileSchema).readonly()),
@@ -232135,11 +232422,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
232135
232422
  * the live hub: one event's `fullFrameBoxed` is 2 824 077 B, base64'd to
232136
232423
  * ~3.8 MB, allocated whole in hub-main's heap, for a list of keys.
232137
232424
  *
232138
- * Same `deviceId` authorization subject as `getEventMedia`, and the same
232139
- * rows — this is a projection of that method, never a different question.
232425
+ * Same `deviceId` authorization subject as `getEventMedia`, the same
232426
+ * REQUIRED `ownerType` (read that method's docblock for the night-time
232427
+ * thumbnail this closes — D482), and the same rows: this is a projection
232428
+ * of that method, never a different question.
232140
232429
  */
232141
232430
  listEventMedia: require_sleep.method(zod.z.object({
232142
- eventId: zod.z.string(),
232431
+ ownerType: EventOwnerTypeSchema,
232432
+ eventId: zod.z.number().int(),
232143
232433
  deviceId: zod.z.number()
232144
232434
  }), zod.z.array(MediaFileInfoSchema).readonly()),
232145
232435
  /**
@@ -237840,8 +238130,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237840
238130
  id: zod.z.string(),
237841
238131
  name: zod.z.string(),
237842
238132
  sampleCount: zod.z.number().int().nonnegative(),
237843
- coverMediaKey: zod.z.string().optional(),
237844
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
238133
+ coverMediaId: zod.z.number().int().optional(),
238134
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
237845
238135
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
237846
238136
  coverBase64: zod.z.string().optional()
237847
238137
  });
@@ -237857,8 +238147,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237857
238147
  enrolledAt: zod.z.number().int(),
237858
238148
  deviceId: zod.z.number().int().optional(),
237859
238149
  source: zod.z.enum(["detected", "photo"]),
237860
- /** The enrolled crop's media key, so the panel can show the evidence. */
237861
- mediaKey: zod.z.string().optional(),
238150
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
238151
+ mediaId: zod.z.number().int().optional(),
237862
238152
  /**
237863
238153
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
237864
238154
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -237927,15 +238217,15 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237927
238217
  */
237928
238218
  cropUrl: zod.z.string().optional(),
237929
238219
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
237930
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
238220
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
237931
238221
  * legacy rows written before design B. */
237932
238222
  faceBbox: BoundingBoxSchema.optional(),
237933
238223
  /** Design B: MediaStore key of the track's native-resolution key frame.
237934
238224
  * Fetch the native JPEG via the event-media data-plane
237935
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
238225
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
237936
238226
  * track produced no key frame (e.g. native/onboard source) — the UI falls
237937
238227
  * back to the inline `base64` face crop. */
237938
- keyFrameMediaKey: zod.z.string().optional(),
238228
+ keyFrameMediaId: zod.z.number().int().optional(),
237939
238229
  /** Winning identity-match cosine (0..1) for this face's track, when an
237940
238230
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
237941
238231
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -237973,7 +238263,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237973
238263
  cohesion: zod.z.number()
237974
238264
  });
237975
238265
  var MediaFileLiteSchema$1 = zod.z.object({
237976
- key: zod.z.string(),
238266
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
238267
+ * (D482). It was the row's composite key, which embedded the owner. */
238268
+ mediaId: zod.z.number().int(),
237977
238269
  kind: zod.z.string(),
237978
238270
  url: zod.z.string(),
237979
238271
  sizeBytes: zod.z.number(),
@@ -237995,7 +238287,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237995
238287
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
237996
238288
  * four times and the viewer holds at `staleTime: 30_000`.
237997
238289
  *
237998
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
238290
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
237999
238291
  * the `event-media` plane serves that key `immutable` with an ETag.
238000
238292
  *
238001
238293
  * **This is an INPUT field, so it does not reach the addon until the
@@ -241265,8 +241557,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241265
241557
  id: zod.z.string(),
241266
241558
  name: zod.z.string(),
241267
241559
  sampleCount: zod.z.number().int().nonnegative(),
241268
- coverMediaKey: zod.z.string().optional(),
241269
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
241560
+ coverMediaId: zod.z.number().int().optional(),
241561
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
241270
241562
  coverBase64: zod.z.string().optional()
241271
241563
  });
241272
241564
  var VehicleSampleInfoSchema = zod.z.object({
@@ -241299,7 +241591,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241299
241591
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
241300
241592
  plateBbox: BoundingBoxSchema.optional(),
241301
241593
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
241302
- keyFrameMediaKey: zod.z.string().optional(),
241594
+ keyFrameMediaId: zod.z.number().int().optional(),
241303
241595
  base64: zod.z.string().optional(),
241304
241596
  /**
241305
241597
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -241310,7 +241602,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241310
241602
  cropUrl: zod.z.string().optional()
241311
241603
  });
241312
241604
  var MediaFileLiteSchema = zod.z.object({
241313
- key: zod.z.string(),
241605
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
241606
+ * (D482). It was the row's composite key, which embedded the owner. */
241607
+ mediaId: zod.z.number().int(),
241314
241608
  kind: zod.z.string(),
241315
241609
  url: zod.z.string(),
241316
241610
  sizeBytes: zod.z.number(),
@@ -241384,7 +241678,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241384
241678
  listVehicles: require_sleep.method(zod.z.object({
241385
241679
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
241386
241680
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
241387
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
241681
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
241388
241682
  * INPUT field: stripped by the hub router until the train ships, which
241389
241683
  * resolves to `false` and is exactly the intended default. */
241390
241684
  includeCrops: zod.z.boolean().optional()
@@ -242897,7 +243191,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
242897
243191
  modelId: zod.z.string(),
242898
243192
  condition: SceneConditionSchema,
242899
243193
  capturedAt: zod.z.number(),
242900
- thumbnailMediaId: zod.z.string().optional(),
243194
+ /**
243195
+ * The reference thumbnail's media ROW id (D482).
243196
+ *
243197
+ * The name already said `mediaId` while the value was the row's composite
243198
+ * key — a leftover that read as done and was not. It is the row's own id
243199
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
243200
+ */
243201
+ thumbnailMediaId: zod.z.number().int().optional(),
242901
243202
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
242902
243203
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
242903
243204
  * normalized rect frame a different piece of world, and the scene would
@@ -244826,7 +245127,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
244826
245127
  /** Enrichment label carried from the source track (identity / plate). */
244827
245128
  label: zod.z.string().optional(),
244828
245129
  /** Native-resolution key-frame media key for the parked object's best image. */
244829
- keyFrameMediaKey: zod.z.string().optional()
245130
+ keyFrameMediaId: zod.z.number().int().optional()
244830
245131
  });
244831
245132
  var CameraOccupancySnapshotSchema = zod.z.object({
244832
245133
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -250039,6 +250340,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
250039
250340
  addonId: null,
250040
250341
  access: "create"
250041
250342
  },
250343
+ "dataStoreProvider.upsert": {
250344
+ capName: "data-store-provider",
250345
+ capScope: "system",
250346
+ addonId: null,
250347
+ access: "create"
250348
+ },
250042
250349
  "dayNight.getOptions": {
250043
250350
  capName: "day-night",
250044
250351
  capScope: "device",
@@ -253903,6 +254210,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
253903
254210
  addonId: null,
253904
254211
  access: "create"
253905
254212
  },
254213
+ "settingsStore.upsert": {
254214
+ capName: "settings-store",
254215
+ capScope: "system",
254216
+ addonId: null,
254217
+ access: "create"
254218
+ },
253906
254219
  "smtpProvider.getStatus": {
253907
254220
  capName: "smtp-provider",
253908
254221
  capScope: "system",
@@ -258420,6 +258733,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
258420
258733
  get: (input) => dispatch("settingsStore", "get", "query", input),
258421
258734
  set: (input) => dispatch("settingsStore", "set", "mutation", input),
258422
258735
  query: (input) => dispatch("settingsStore", "query", "query", input),
258736
+ upsert: (input) => dispatch("settingsStore", "upsert", "mutation", input),
258423
258737
  insert: (input) => dispatch("settingsStore", "insert", "mutation", input),
258424
258738
  insertMany: (input) => dispatch("settingsStore", "insertMany", "mutation", input),
258425
258739
  update: (input) => dispatch("settingsStore", "update", "mutation", input),
@@ -261567,6 +261881,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
261567
261881
  exports.EventMediaCoverageSchema = EventMediaCoverageSchema;
261568
261882
  exports.EventMediaKindSchema = EventMediaKindSchema;
261569
261883
  exports.EventMediaProductionSchema = EventMediaProductionSchema;
261884
+ exports.EventOwnerTypeSchema = EventOwnerTypeSchema;
261570
261885
  exports.EventSourceType = require_enums2.EventSourceType$1;
261571
261886
  exports.ExportBytesSchema = ExportBytesSchema;
261572
261887
  exports.ExportDenseRangeSchema = ExportDenseRangeSchema;
@@ -262539,6 +262854,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262539
262854
  exports.isFirstLevelMacroClass = isFirstLevelMacroClass;
262540
262855
  exports.isIsolatedBuiltin = isIsolatedBuiltin;
262541
262856
  exports.isLocationEnabled = isLocationEnabled;
262857
+ exports.isMediaOwnerType = isMediaOwnerType;
262542
262858
  exports.isNode = isNode;
262543
262859
  exports.isObjectInput = isObjectInput;
262544
262860
  exports.isOccupancyRule = isOccupancyRule;
@@ -263394,6 +263710,7 @@ var require_server_root = __commonJS({
263394
263710
  devUploadsDir: /* @__PURE__ */ __name(() => devUploadsDir, "devUploadsDir"),
263395
263711
  emptyServerRootState: /* @__PURE__ */ __name(() => emptyServerRootState, "emptyServerRootState"),
263396
263712
  findMissingNativePrebuilds: /* @__PURE__ */ __name(() => findMissingNativePrebuilds, "findMissingNativePrebuilds"),
263713
+ findUnappliedClosurePatches: /* @__PURE__ */ __name(() => findUnappliedClosurePatches, "findUnappliedClosurePatches"),
263397
263714
  isDevChannelVersion: /* @__PURE__ */ __name(() => isDevChannelVersion, "isDevChannelVersion"),
263398
263715
  isHostExternal: /* @__PURE__ */ __name(() => isHostExternal, "isHostExternal"),
263399
263716
  isServerRootState: /* @__PURE__ */ __name(() => isServerRootState, "isServerRootState"),
@@ -263798,6 +264115,58 @@ var require_server_root = __commonJS({
263798
264115
  return missing;
263799
264116
  }
263800
264117
  __name(findMissingNativePrebuilds, "findMissingNativePrebuilds");
264118
+ var CLOSURE_PATCH_PAYLOAD = [
264119
+ "node_modules",
264120
+ "@camstack",
264121
+ "server",
264122
+ "dist",
264123
+ "closure-patches"
264124
+ ];
264125
+ var CLOSURE_PATCH_MANIFEST = "patch-reach.json";
264126
+ function fileContains(file, marker) {
264127
+ try {
264128
+ return fs3.readFileSync(file, "utf-8").includes(marker);
264129
+ } catch {
264130
+ return false;
264131
+ }
264132
+ }
264133
+ __name(fileContains, "fileContains");
264134
+ function findUnappliedClosurePatches(closureDir) {
264135
+ const payloadDir = path3.join(closureDir, ...CLOSURE_PATCH_PAYLOAD);
264136
+ let manifest;
264137
+ try {
264138
+ const raw = JSON.parse(fs3.readFileSync(path3.join(payloadDir, CLOSURE_PATCH_MANIFEST), "utf-8"));
264139
+ if (typeof raw !== "object" || raw === null) return [];
264140
+ manifest = raw;
264141
+ } catch {
264142
+ return [];
264143
+ }
264144
+ if (!Array.isArray(manifest.patches)) return [];
264145
+ const nm = path3.join(closureDir, "node_modules");
264146
+ const missing = [];
264147
+ for (const raw of manifest.patches) {
264148
+ if (raw.reach !== "closure-postinstall") continue;
264149
+ const pkg = raw.package;
264150
+ const markers = raw.markers;
264151
+ if (typeof pkg !== "string" || typeof markers !== "object" || markers === null) continue;
264152
+ const pkgDir = path3.join(nm, pkg);
264153
+ if (!fs3.existsSync(pkgDir)) {
264154
+ continue;
264155
+ }
264156
+ for (const [rel, list] of Object.entries(markers)) {
264157
+ if (!Array.isArray(list)) continue;
264158
+ const target = path3.join(pkgDir, ...rel.split("/"));
264159
+ for (const marker of list) {
264160
+ if (typeof marker !== "string") continue;
264161
+ if (!fileContains(target, marker)) {
264162
+ missing.push(`${pkg}/${rel}: ${marker}`);
264163
+ }
264164
+ }
264165
+ }
264166
+ }
264167
+ return missing;
264168
+ }
264169
+ __name(findUnappliedClosurePatches, "findUnappliedClosurePatches");
263801
264170
  function rmrf(target) {
263802
264171
  try {
263803
264172
  fs3.rmSync(target, {
@@ -264734,6 +265103,10 @@ var require_server_root = __commonJS({
264734
265103
  if (missingNatives.length > 0) {
264735
265104
  throw new Error(`staged closure missing native prebuilds: ${missingNatives.join(", ")} \u2014 refusing to arm a swap that would break the forked runners`);
264736
265105
  }
265106
+ const unpatched = findUnappliedClosurePatches(stagingDir);
265107
+ if (unpatched.length > 0) {
265108
+ throw new Error(`staged closure did not apply its shipped patches: ${unpatched.join(", ")} \u2014 refusing to arm a swap into an unpatched closure`);
265109
+ }
264737
265110
  return stagingDir;
264738
265111
  } catch (err) {
264739
265112
  await fs6.promises.rm(stagingDir, {