@camstack/addon-export-alexa 1.2.8 → 1.2.10

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.
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  //#endregion
27
27
  let node_crypto = require("node:crypto");
28
28
  node_crypto = __toESM(node_crypto);
29
- //#region ../types/dist/event-category-Bz24uP1U.mjs
29
+ //#region ../types/dist/event-category-41fKf-q9.mjs
30
30
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
31
31
  EventCategory["SystemBoot"] = "system.boot";
32
32
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -86,6 +86,26 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
86
86
  */
87
87
  EventCategory["AddonRetryScheduled"] = "addon.retry-scheduled";
88
88
  /**
89
+ * A liveness invariant of this node is false — it has no devices, every
90
+ * camera is offline, or a camera that was recording has stopped producing
91
+ * segments. Emitted by the `liveness-monitor` builtin, once per fault (the
92
+ * `findingId` is stable across ticks), only after its boot grace period.
93
+ * AlertCenter raises a persistent operator-visible alert.
94
+ *
95
+ * It exists because on 2026-08-03 the hub ran four hours with zero devices
96
+ * and zero recordings while every surface stayed quiet.
97
+ *
98
+ * Payload: `{ findingId, severity, title, message, deviceId? }`.
99
+ */
100
+ EventCategory["SystemLivenessFailed"] = "system.liveness-failed";
101
+ /**
102
+ * A previously reported liveness fault is true again. AlertCenter dismisses
103
+ * the matching `SystemLivenessFailed` alert.
104
+ *
105
+ * Payload: `{ findingId }`.
106
+ */
107
+ EventCategory["SystemLivenessRecovered"] = "system.liveness-recovered";
108
+ /**
89
109
  * Monitor is attempting to reload a failed addon NOW. UI uses this
90
110
  * to show a spinner during the retry attempt. Same transient nature
91
111
  * as AddonRetryScheduled.
@@ -7476,14 +7496,7 @@ var RecordingConfigSchema = object({
7476
7496
  * windows only — existing sheets are immutable, and each window's index
7477
7497
  * carries its own tile dims so mixed-preset history renders correctly.
7478
7498
  */
7479
- scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
7480
- /**
7481
- * OPT-IN thumbnail-strip generation for this camera: every keyframe of the
7482
- * low recording saved as a JPEG (the fast-drag scrub depth), a derived
7483
- * cache that eviction reclaims with the footage. Absent/false = no strips
7484
- * are written and scrub reads exact keyframes at every velocity.
7485
- */
7486
- stripsEnabled: boolean().optional()
7499
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7487
7500
  }).strict();
7488
7501
  /**
7489
7502
  * Ops-log — the durable, append-only operations audit shared by the
@@ -7545,7 +7558,7 @@ var OpsLogQueryInputSchema = object({
7545
7558
  /**
7546
7559
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
7547
7560
  *
7548
- * One shape shared by the recorder's `relocateFootage` (segments + strips) and
7561
+ * One shape shared by the recorder's `relocateFootage` (segments) and
7549
7562
  * pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
7550
7563
  * page renders both movers with one component. Jobs are in-RAM (a restart
7551
7564
  * forgets them — re-running is safe by construction: copy-if-absent, delete
@@ -7567,7 +7580,7 @@ var RelocateJobSchema = object({
7567
7580
  toLocationId: string(),
7568
7581
  /** Scoped device, or null = every device. */
7569
7582
  deviceId: number().nullable(),
7570
- /** What the job moves (owner-addon specific: segments/strips or media). */
7583
+ /** What the job moves (owner-addon specific: segments or media). */
7571
7584
  entities: array(string()),
7572
7585
  filesMoved: number().int(),
7573
7586
  bytesMoved: number().int(),
@@ -7581,7 +7594,7 @@ var RelocateFootageInputSchema = object({
7581
7594
  deviceId: number().optional(),
7582
7595
  fromLocationId: string(),
7583
7596
  toLocationId: string(),
7584
- entities: array(_enum(["segments", "strips"])).optional(),
7597
+ entities: array(_enum(["segments"])).optional(),
7585
7598
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7586
7599
  * never allowed to starve live writers. */
7587
7600
  throttleMbps: number().min(1).max(1e3).optional()
@@ -9318,11 +9331,13 @@ var NcZoneConditionSchema = object({
9318
9331
  /** Quantifier over `ids` — at least one / every one visited. */
9319
9332
  match: _enum(["any", "all"]).default("any")
9320
9333
  });
9321
- /**
9322
- * The P1 condition set — a flat AND of groups; absent group = pass;
9323
- * membership lists are OR within the list (spec §2.3).
9324
- */
9325
9334
  var NcConditionsSchema = object({
9335
+ /** Gate on ANOTHER device's current state (the alarm armed, a switch on). */
9336
+ deviceState: object({
9337
+ deviceId: number().int(),
9338
+ /** Any of these matches. */
9339
+ states: array(string().min(1)).min(1)
9340
+ }).optional(),
9326
9341
  /** Device scope — absent = all devices. */
9327
9342
  devices: array(number()).optional(),
9328
9343
  /** Detector class names (any overlap with the record's class set). */
@@ -9523,6 +9538,14 @@ var NcMediaPolicySchema = object({
9523
9538
  clipPreRollSec: number().int().min(0).max(30).optional(),
9524
9539
  clipPostRollSec: number().int().min(0).max(30).optional(),
9525
9540
  /**
9541
+ * Playback rate of the attached gif / clip. Absent = 2x.
9542
+ *
9543
+ * A notification clip is GLANCED at on a lock screen, not watched: at real
9544
+ * time an eight-second passage is eight seconds of the recipient's attention
9545
+ * and twice the bytes. 1 is real time for the operator who wants it.
9546
+ */
9547
+ clipSpeed: number().min(1).max(8).optional(),
9548
+ /**
9526
9549
  * Which stream profile the footage is cut from. Absent = the CHEAPEST
9527
9550
  * assigned profile: a notification is watched on a phone, so the 4K
9528
9551
  * rendition would burn CPU to produce a file the client downscales anyway.
@@ -9594,7 +9617,21 @@ var NcRuleInputSchema = object({
9594
9617
  * behaviour, visible to all, read-only in the viewer). Present = personal
9595
9618
  * rule owned by this userId. Server-stamped; never trusted from a client.
9596
9619
  */
9597
- ownerUserId: string().optional()
9620
+ ownerUserId: string().optional(),
9621
+ /**
9622
+ * May a non-admin snooze this rule for EVERYONE, not just themselves?
9623
+ *
9624
+ * A snooze is personal by default — it silences the person who set it. This
9625
+ * opts THIS rule into the "the gardener is here all afternoon" case, where
9626
+ * silencing the camera for the whole household is legitimate. It silences
9627
+ * other people, so it is off unless a rule deliberately allows it.
9628
+ *
9629
+ * `.optional()`, deliberately NOT `.default()`: a Zod default does not run on
9630
+ * the addon cap path (three production failures in one day), so absent is
9631
+ * read as `false` by {@link canSetGlobal} in the engine. Admins are not bound
9632
+ * by this flag — see the scope rules on that function.
9633
+ */
9634
+ snoozeAllowGlobal: boolean().optional()
9598
9635
  });
9599
9636
  /**
9600
9637
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -9665,7 +9702,8 @@ var NcConditionDescriptorSchema = object({
9665
9702
  "packagePhase",
9666
9703
  "crossingSelect",
9667
9704
  "polygonDraw",
9668
- "occupancy"
9705
+ "occupancy",
9706
+ "deviceState"
9669
9707
  ]),
9670
9708
  operator: _enum([
9671
9709
  "in",
@@ -9679,7 +9717,28 @@ var NcConditionDescriptorSchema = object({
9679
9717
  /** Which delivery kinds the condition applies to. */
9680
9718
  appliesTo: array(NcDeliverySchema),
9681
9719
  phase: string(),
9682
- description: string().optional()
9720
+ description: string().optional(),
9721
+ /**
9722
+ * The CHOICES for a single-choice widget (`sourceSelect`, `crossingSelect`,
9723
+ * `packagePhase`, …), served with the descriptor.
9724
+ *
9725
+ * Before this the descriptor said which widget to render and not what to put
9726
+ * in it, so every option list lived in three places: this file's enums, the
9727
+ * admin's `NC_*_OPTIONS` and the viewer's `NC_*_VALUES`. That triple mirror
9728
+ * is the drift that emptied the viewer's rule editor on 2026-08-04 — the app
9729
+ * mirrors the cap by hand, so it is only ever as current as its last build.
9730
+ *
9731
+ * With the options on the wire, a condition of an EXISTING `valueType` costs
9732
+ * zero client changes. Clients keep a local fallback for an older hub that
9733
+ * does not send them; absent here is "use your own list", not "no choices".
9734
+ */
9735
+ options: array(object({
9736
+ /** Written to the rule verbatim. `''` means the ABSENT state. */
9737
+ value: string(),
9738
+ label: string(),
9739
+ /** What THIS choice matches — shown one at a time, under the control. */
9740
+ hint: string().optional()
9741
+ })).readonly().optional()
9683
9742
  });
9684
9743
  /**
9685
9744
  * The delivery lifecycle status of a history row — a straight read of the
@@ -9764,6 +9823,74 @@ var NcHistoryFilterSchema = object({
9764
9823
  until: number().optional(),
9765
9824
  limit: number().int().min(1).max(500).default(100)
9766
9825
  });
9826
+ /**
9827
+ * What a snooze covers. Broader scopes win when several overlap, so one window
9828
+ * leaves ONE digest rather than a rule snooze and a whole-feed snooze both
9829
+ * summarising the same silence.
9830
+ */
9831
+ var NcSnoozeScopeSchema = _enum([
9832
+ "rule",
9833
+ "device",
9834
+ "all"
9835
+ ]);
9836
+ /**
9837
+ * Client-authored snooze. The server stamps `userId`, `startedAt` and
9838
+ * `expiresAt` — a DURATION is sent rather than an instant so a client with a
9839
+ * skewed clock cannot author a window that is already over, or never ends.
9840
+ */
9841
+ var NcSnoozeInputSchema = object({
9842
+ scope: NcSnoozeScopeSchema,
9843
+ /** Required when `scope: 'rule'` — a scoped snooze with no id matches
9844
+ * NOTHING rather than degrading to "everything". */
9845
+ ruleId: string().optional(),
9846
+ /** Required when `scope: 'device'`. */
9847
+ deviceId: number().int().optional(),
9848
+ durationMinutes: number().int().min(1).max(1440),
9849
+ /**
9850
+ * Silence this for EVERY recipient, not just the caller. Permission is
9851
+ * checked server-side (the rule's `snoozeAllowGlobal`, or admin for the
9852
+ * broader scopes). Absent = personal.
9853
+ */
9854
+ global: boolean().optional(),
9855
+ /**
9856
+ * Deliver a summary of what was suppressed when the window ends. Absent =
9857
+ * ON: someone silencing a nuisance camera wants it off, someone silencing a
9858
+ * SECURITY camera wants to know what they missed, and choosing "off" for
9859
+ * everybody is how a snooze becomes an outage. Resolved to a concrete
9860
+ * boolean by the server at create time — never left to a Zod default, which
9861
+ * does not run on the addon cap path.
9862
+ */
9863
+ summary: boolean().optional()
9864
+ });
9865
+ /** A persisted snooze window. */
9866
+ var NcSnoozeSchema = object({
9867
+ id: string(),
9868
+ /** Who set it. Also who it silences, unless `global`. */
9869
+ userId: string(),
9870
+ scope: NcSnoozeScopeSchema,
9871
+ ruleId: string().optional(),
9872
+ deviceId: number().int().optional(),
9873
+ startedAt: number(),
9874
+ /** Exclusive: at exactly this instant the snooze is over. Expiry is a
9875
+ * COMPARISON, not a job — no sweeper can leave the operator silenced. */
9876
+ expiresAt: number(),
9877
+ global: boolean(),
9878
+ summary: boolean(),
9879
+ /** When the end-of-window digest went out. Absent = not sent (yet, or the
9880
+ * window has not closed, or `summary` is false). */
9881
+ digestSentAt: number().optional()
9882
+ });
9883
+ object({
9884
+ snoozeId: string(),
9885
+ targetId: string(),
9886
+ ruleId: string(),
9887
+ ruleName: string(),
9888
+ deviceId: number().int(),
9889
+ /** How many notifications this snooze hid for that pair. */
9890
+ count: number().int(),
9891
+ firstAt: number(),
9892
+ lastAt: number()
9893
+ });
9767
9894
  method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), method(object({ ruleId: string() }), object({ rule: NcRuleSchema.nullable() }), { auth: "admin" }), method(object({ rule: NcRuleInputSchema }), object({ rule: NcRuleSchema }), {
9768
9895
  kind: "mutation",
9769
9896
  auth: "admin",
@@ -9793,7 +9920,13 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
9793
9920
  }), method(object({}), object({
9794
9921
  catalog: array(NcConditionDescriptorSchema),
9795
9922
  taxonomy: NcTaxonomySchema.optional()
9796
- })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" });
9923
+ })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
9924
+ kind: "mutation",
9925
+ caller: "required"
9926
+ }), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
9927
+ kind: "mutation",
9928
+ caller: "required"
9929
+ });
9797
9930
  /**
9798
9931
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
9799
9932
  *
@@ -10541,7 +10674,15 @@ method(object({
10541
10674
  format: _enum(["gif", "mp4"]).default("gif"),
10542
10675
  maxWidth: number().int().min(120).max(1920).default(480),
10543
10676
  /** GIF only — MP4 keeps the source cadence. */
10544
- fps: number().int().min(1).max(15).default(5)
10677
+ fps: number().int().min(1).max(15).default(5),
10678
+ /**
10679
+ * Playback rate. A notification clip is GLANCED at on a lock screen,
10680
+ * not watched, so 2x is the default: the recipient sees the whole
10681
+ * passage in half the time and the GIF is half the bytes. `1` is real
10682
+ * time. Applies to MP4 as well — the operator set a speed, not a GIF
10683
+ * speed.
10684
+ */
10685
+ speed: number().min(1).max(8).default(2)
10545
10686
  }), object({
10546
10687
  base64: string(),
10547
10688
  mime: string(),
@@ -15327,6 +15468,210 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15327
15468
  kind: "mutation",
15328
15469
  auth: "admin"
15329
15470
  });
15471
+ /**
15472
+ * Query filter for settings-store collections.
15473
+ */
15474
+ var QueryFilterSchema = object({
15475
+ where: record(string(), unknown()).optional(),
15476
+ whereIn: record(string(), array(unknown())).optional(),
15477
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
15478
+ orderBy: object({
15479
+ field: string(),
15480
+ direction: _enum(["asc", "desc"])
15481
+ }).optional(),
15482
+ limit: number().optional(),
15483
+ offset: number().optional()
15484
+ });
15485
+ /**
15486
+ * The predicate half of a filter, for BULK MUTATIONS.
15487
+ *
15488
+ * Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
15489
+ * meaning for a statement that rewrites a set, and accepting them would invite
15490
+ * a caller to believe `limit` bounds the damage. Every field is optional here
15491
+ * only so the shape stays composable — the implementation REJECTS a filter
15492
+ * that compiles to no predicate, because that is the whole collection.
15493
+ */
15494
+ var MutationFilterSchema = object({
15495
+ where: record(string(), unknown()).optional(),
15496
+ whereIn: record(string(), array(unknown())).optional(),
15497
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
15498
+ });
15499
+ /** A single stored record: `{ id, data }`. */
15500
+ var SettingsRecordSchema = object({
15501
+ id: string(),
15502
+ data: record(string(), unknown())
15503
+ });
15504
+ /**
15505
+ * Column declaration for a structured (SQL-backed) collection.
15506
+ *
15507
+ * Logical types — the backend translates each to the matching SQLite
15508
+ * storage class and handles per-type marshaling:
15509
+ * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
15510
+ * - `JSON` — TEXT under the hood; serialised on write, parsed on read
15511
+ * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
15512
+ */
15513
+ var CollectionColumnSchema = object({
15514
+ name: string(),
15515
+ type: _enum([
15516
+ "TEXT",
15517
+ "INTEGER",
15518
+ "REAL",
15519
+ "JSON",
15520
+ "BOOLEAN"
15521
+ ]),
15522
+ primaryKey: boolean().optional(),
15523
+ notNull: boolean().optional(),
15524
+ unique: boolean().optional(),
15525
+ /**
15526
+ * Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
15527
+ * columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
15528
+ * collection surface simply cannot express their existing tables — which is
15529
+ * why they were still on the uncapped `table*` API.
15530
+ */
15531
+ defaultValue: union([
15532
+ string(),
15533
+ number(),
15534
+ boolean()
15535
+ ]).optional()
15536
+ });
15537
+ var CollectionIndexSchema = object({
15538
+ name: string(),
15539
+ columns: array(string()).readonly(),
15540
+ unique: boolean().optional()
15541
+ });
15542
+ method(object({
15543
+ namespace: string().optional(),
15544
+ collection: string(),
15545
+ key: string()
15546
+ }), unknown()), method(object({
15547
+ namespace: string().optional(),
15548
+ collection: string(),
15549
+ key: string(),
15550
+ value: unknown()
15551
+ }), _void(), { kind: "mutation" }), method(object({
15552
+ namespace: string().optional(),
15553
+ collection: string(),
15554
+ filter: QueryFilterSchema.optional()
15555
+ }), array(SettingsRecordSchema).readonly()), method(object({
15556
+ namespace: string().optional(),
15557
+ collection: string(),
15558
+ record: SettingsRecordSchema
15559
+ }), _void(), { kind: "mutation" }), method(object({
15560
+ namespace: string().optional(),
15561
+ collection: string(),
15562
+ id: string(),
15563
+ data: record(string(), unknown())
15564
+ }), _void(), { kind: "mutation" }), method(object({
15565
+ namespace: string().optional(),
15566
+ collection: string(),
15567
+ key: string()
15568
+ }), _void(), { kind: "mutation" }), method(object({
15569
+ namespace: string().optional(),
15570
+ collection: string(),
15571
+ filter: MutationFilterSchema
15572
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
15573
+ namespace: string().optional(),
15574
+ collection: string(),
15575
+ filter: MutationFilterSchema,
15576
+ data: record(string(), unknown())
15577
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
15578
+ namespace: string().optional(),
15579
+ collection: string(),
15580
+ filter: QueryFilterSchema.optional()
15581
+ }), number()), method(object({
15582
+ namespace: string().optional(),
15583
+ collection: string(),
15584
+ field: string(),
15585
+ bucketSize: number().int().positive(),
15586
+ origin: number().int(),
15587
+ filter: QueryFilterSchema.optional()
15588
+ }), array(object({
15589
+ bucket: number().int(),
15590
+ count: number().int()
15591
+ })).readonly()), method(object({
15592
+ namespace: string().optional(),
15593
+ collection: string()
15594
+ }), boolean()), method(object({
15595
+ namespace: string().optional(),
15596
+ collection: string(),
15597
+ columns: array(CollectionColumnSchema).readonly(),
15598
+ indexes: array(CollectionIndexSchema).readonly().optional()
15599
+ }), _void(), { kind: "mutation" });
15600
+ /**
15601
+ * What one engine says about itself. The orchestrator uses `kind` to pick
15602
+ * a registrant for a collection; `engineId` is what a log line names when
15603
+ * a call is routed or refused.
15604
+ */
15605
+ var EngineInfoSchema = object({
15606
+ engineId: string(),
15607
+ /**
15608
+ * `relational` — rows, columns, indexes, the surface `settings-store`
15609
+ * has always described. `vector` — an embedding store answering
15610
+ * similarity queries. A registrant declares exactly one; an engine that
15611
+ * does both registers twice, because "both" would make the routing
15612
+ * decision ambiguous at exactly the point it must not be.
15613
+ */
15614
+ kind: _enum(["relational", "vector"]),
15615
+ displayName: string()
15616
+ });
15617
+ method(_void(), EngineInfoSchema), method(object({
15618
+ namespace: string().optional(),
15619
+ collection: string(),
15620
+ key: string()
15621
+ }), unknown()), method(object({
15622
+ namespace: string().optional(),
15623
+ collection: string(),
15624
+ key: string(),
15625
+ value: unknown()
15626
+ }), _void(), { kind: "mutation" }), method(object({
15627
+ namespace: string().optional(),
15628
+ collection: string(),
15629
+ filter: QueryFilterSchema.optional()
15630
+ }), array(SettingsRecordSchema).readonly()), method(object({
15631
+ namespace: string().optional(),
15632
+ collection: string(),
15633
+ record: SettingsRecordSchema
15634
+ }), _void(), { kind: "mutation" }), method(object({
15635
+ namespace: string().optional(),
15636
+ collection: string(),
15637
+ id: string(),
15638
+ data: record(string(), unknown())
15639
+ }), _void(), { kind: "mutation" }), method(object({
15640
+ namespace: string().optional(),
15641
+ collection: string(),
15642
+ key: string()
15643
+ }), _void(), { kind: "mutation" }), method(object({
15644
+ namespace: string().optional(),
15645
+ collection: string(),
15646
+ filter: MutationFilterSchema
15647
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
15648
+ namespace: string().optional(),
15649
+ collection: string(),
15650
+ filter: MutationFilterSchema,
15651
+ data: record(string(), unknown())
15652
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
15653
+ namespace: string().optional(),
15654
+ collection: string(),
15655
+ filter: QueryFilterSchema.optional()
15656
+ }), number()), method(object({
15657
+ namespace: string().optional(),
15658
+ collection: string(),
15659
+ field: string(),
15660
+ bucketSize: number().int().positive(),
15661
+ origin: number().int(),
15662
+ filter: QueryFilterSchema.optional()
15663
+ }), array(object({
15664
+ bucket: number().int(),
15665
+ count: number().int()
15666
+ })).readonly()), method(object({
15667
+ namespace: string().optional(),
15668
+ collection: string()
15669
+ }), boolean()), method(object({
15670
+ namespace: string().optional(),
15671
+ collection: string(),
15672
+ columns: array(CollectionColumnSchema).readonly(),
15673
+ indexes: array(CollectionIndexSchema).readonly().optional()
15674
+ }), _void(), { kind: "mutation" });
15330
15675
  DeviceType.Camera;
15331
15676
  /**
15332
15677
  * `device-adoption` — generic discovery + adoption surface,
@@ -18590,6 +18935,28 @@ var ServerUpdateStateSchema = _enum([
18590
18935
  "pending-restart",
18591
18936
  "awaiting-confirmation"
18592
18937
  ]);
18938
+ var ImageContractSchema = object({
18939
+ state: _enum([
18940
+ "in-sync",
18941
+ "behind-patch",
18942
+ "behind-series",
18943
+ "ahead",
18944
+ "unknown"
18945
+ ]),
18946
+ /** The baked seed closure version — the image/app-bundle fingerprint. */
18947
+ seedVersion: string().nullable(),
18948
+ /** Best-known version the deployment contract delivers today. */
18949
+ contractVersion: string().nullable(),
18950
+ /**
18951
+ * Where `contractVersion` came from: a real registry check (`registry`), or
18952
+ * the node's own running version (`running` — a node can never run code
18953
+ * newer than the newest release, so `seed < running` proves image staleness
18954
+ * even before any registry check has run).
18955
+ */
18956
+ contractSource: _enum(["registry", "running"]).nullable(),
18957
+ /** One operator-grade sentence: this node runs image X; the contract says Y. */
18958
+ message: string()
18959
+ });
18593
18960
  var ServerRollbackInfoSchema = object({
18594
18961
  /** The version that failed (or was manually rolled back). */
18595
18962
  fromVersion: string(),
@@ -18626,7 +18993,12 @@ var ServerPackageStatusSchema = object({
18626
18993
  * versions are being IGNORED. Surfaced as a warning in the UI.
18627
18994
  */
18628
18995
  stateFileCorrupt: boolean(),
18629
- lastCheckedAtMs: number().nullable()
18996
+ lastCheckedAtMs: number().nullable(),
18997
+ /**
18998
+ * Seed-vs-contract verdict (see {@link ImageContractSchema}). Optional for
18999
+ * version skew: an older provider's payload simply omits it.
19000
+ */
19001
+ imageContract: ImageContractSchema.optional()
18630
19002
  });
18631
19003
  var ServerUpdateCheckResultSchema = object({
18632
19004
  packageName: string(),
@@ -18661,101 +19033,6 @@ version: string().optional() }), ServerUpdateActionResultSchema, {
18661
19033
  auth: "admin"
18662
19034
  });
18663
19035
  /**
18664
- * Query filter for settings-store collections.
18665
- */
18666
- var QueryFilterSchema = object({
18667
- where: record(string(), unknown()).optional(),
18668
- whereIn: record(string(), array(unknown())).optional(),
18669
- whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
18670
- orderBy: object({
18671
- field: string(),
18672
- direction: _enum(["asc", "desc"])
18673
- }).optional(),
18674
- limit: number().optional(),
18675
- offset: number().optional()
18676
- });
18677
- /** A single stored record: `{ id, data }`. */
18678
- var SettingsRecordSchema = object({
18679
- id: string(),
18680
- data: record(string(), unknown())
18681
- });
18682
- /**
18683
- * Column declaration for a structured (SQL-backed) collection.
18684
- *
18685
- * Logical types — the backend translates each to the matching SQLite
18686
- * storage class and handles per-type marshaling:
18687
- * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
18688
- * - `JSON` — TEXT under the hood; serialised on write, parsed on read
18689
- * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
18690
- */
18691
- var CollectionColumnSchema = object({
18692
- name: string(),
18693
- type: _enum([
18694
- "TEXT",
18695
- "INTEGER",
18696
- "REAL",
18697
- "JSON",
18698
- "BOOLEAN"
18699
- ]),
18700
- primaryKey: boolean().optional(),
18701
- notNull: boolean().optional(),
18702
- unique: boolean().optional()
18703
- });
18704
- var CollectionIndexSchema = object({
18705
- name: string(),
18706
- columns: array(string()).readonly(),
18707
- unique: boolean().optional()
18708
- });
18709
- method(object({
18710
- namespace: string().optional(),
18711
- collection: string(),
18712
- key: string()
18713
- }), unknown()), method(object({
18714
- namespace: string().optional(),
18715
- collection: string(),
18716
- key: string(),
18717
- value: unknown()
18718
- }), _void(), { kind: "mutation" }), method(object({
18719
- namespace: string().optional(),
18720
- collection: string(),
18721
- filter: QueryFilterSchema.optional()
18722
- }), array(SettingsRecordSchema).readonly()), method(object({
18723
- namespace: string().optional(),
18724
- collection: string(),
18725
- record: SettingsRecordSchema
18726
- }), _void(), { kind: "mutation" }), method(object({
18727
- namespace: string().optional(),
18728
- collection: string(),
18729
- id: string(),
18730
- data: record(string(), unknown())
18731
- }), _void(), { kind: "mutation" }), method(object({
18732
- namespace: string().optional(),
18733
- collection: string(),
18734
- key: string()
18735
- }), _void(), { kind: "mutation" }), method(object({
18736
- namespace: string().optional(),
18737
- collection: string(),
18738
- filter: QueryFilterSchema.optional()
18739
- }), number()), method(object({
18740
- namespace: string().optional(),
18741
- collection: string(),
18742
- field: string(),
18743
- bucketSize: number().int().positive(),
18744
- origin: number().int(),
18745
- filter: QueryFilterSchema.optional()
18746
- }), array(object({
18747
- bucket: number().int(),
18748
- count: number().int()
18749
- })).readonly()), method(object({
18750
- namespace: string().optional(),
18751
- collection: string()
18752
- }), boolean()), method(object({
18753
- namespace: string().optional(),
18754
- collection: string(),
18755
- columns: array(CollectionColumnSchema).readonly(),
18756
- indexes: array(CollectionIndexSchema).readonly().optional()
18757
- }), _void(), { kind: "mutation" });
18758
- /**
18759
19036
  * `smtp-provider` — pluggable email delivery surface.
18760
19037
  *
18761
19038
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
@@ -22654,6 +22931,84 @@ Object.freeze({
22654
22931
  addonId: null,
22655
22932
  access: "view"
22656
22933
  },
22934
+ "dataStoreProvider.count": {
22935
+ capName: "data-store-provider",
22936
+ capScope: "system",
22937
+ addonId: null,
22938
+ access: "view"
22939
+ },
22940
+ "dataStoreProvider.declareCollection": {
22941
+ capName: "data-store-provider",
22942
+ capScope: "system",
22943
+ addonId: null,
22944
+ access: "create"
22945
+ },
22946
+ "dataStoreProvider.delete": {
22947
+ capName: "data-store-provider",
22948
+ capScope: "system",
22949
+ addonId: null,
22950
+ access: "delete"
22951
+ },
22952
+ "dataStoreProvider.deleteWhere": {
22953
+ capName: "data-store-provider",
22954
+ capScope: "system",
22955
+ addonId: null,
22956
+ access: "delete"
22957
+ },
22958
+ "dataStoreProvider.get": {
22959
+ capName: "data-store-provider",
22960
+ capScope: "system",
22961
+ addonId: null,
22962
+ access: "view"
22963
+ },
22964
+ "dataStoreProvider.getEngineInfo": {
22965
+ capName: "data-store-provider",
22966
+ capScope: "system",
22967
+ addonId: null,
22968
+ access: "view"
22969
+ },
22970
+ "dataStoreProvider.histogram": {
22971
+ capName: "data-store-provider",
22972
+ capScope: "system",
22973
+ addonId: null,
22974
+ access: "view"
22975
+ },
22976
+ "dataStoreProvider.insert": {
22977
+ capName: "data-store-provider",
22978
+ capScope: "system",
22979
+ addonId: null,
22980
+ access: "create"
22981
+ },
22982
+ "dataStoreProvider.isEmpty": {
22983
+ capName: "data-store-provider",
22984
+ capScope: "system",
22985
+ addonId: null,
22986
+ access: "view"
22987
+ },
22988
+ "dataStoreProvider.query": {
22989
+ capName: "data-store-provider",
22990
+ capScope: "system",
22991
+ addonId: null,
22992
+ access: "view"
22993
+ },
22994
+ "dataStoreProvider.set": {
22995
+ capName: "data-store-provider",
22996
+ capScope: "system",
22997
+ addonId: null,
22998
+ access: "create"
22999
+ },
23000
+ "dataStoreProvider.update": {
23001
+ capName: "data-store-provider",
23002
+ capScope: "system",
23003
+ addonId: null,
23004
+ access: "create"
23005
+ },
23006
+ "dataStoreProvider.updateWhere": {
23007
+ capName: "data-store-provider",
23008
+ capScope: "system",
23009
+ addonId: null,
23010
+ access: "create"
23011
+ },
22657
23012
  "dayNight.getOptions": {
22658
23013
  capName: "day-night",
22659
23014
  capScope: "device",
@@ -24448,12 +24803,24 @@ Object.freeze({
24448
24803
  addonId: null,
24449
24804
  access: "create"
24450
24805
  },
24806
+ "notificationRules.cancelSnooze": {
24807
+ capName: "notification-rules",
24808
+ capScope: "system",
24809
+ addonId: null,
24810
+ access: "create"
24811
+ },
24451
24812
  "notificationRules.createRule": {
24452
24813
  capName: "notification-rules",
24453
24814
  capScope: "system",
24454
24815
  addonId: null,
24455
24816
  access: "create"
24456
24817
  },
24818
+ "notificationRules.createSnooze": {
24819
+ capName: "notification-rules",
24820
+ capScope: "system",
24821
+ addonId: null,
24822
+ access: "create"
24823
+ },
24457
24824
  "notificationRules.deleteRule": {
24458
24825
  capName: "notification-rules",
24459
24826
  capScope: "system",
@@ -24484,6 +24851,12 @@ Object.freeze({
24484
24851
  addonId: null,
24485
24852
  access: "view"
24486
24853
  },
24854
+ "notificationRules.listSnoozes": {
24855
+ capName: "notification-rules",
24856
+ capScope: "system",
24857
+ addonId: null,
24858
+ access: "view"
24859
+ },
24487
24860
  "notificationRules.setRuleEnabled": {
24488
24861
  capName: "notification-rules",
24489
24862
  capScope: "system",
@@ -25732,6 +26105,12 @@ Object.freeze({
25732
26105
  addonId: null,
25733
26106
  access: "delete"
25734
26107
  },
26108
+ "settingsStore.deleteWhere": {
26109
+ capName: "settings-store",
26110
+ capScope: "system",
26111
+ addonId: null,
26112
+ access: "delete"
26113
+ },
25735
26114
  "settingsStore.get": {
25736
26115
  capName: "settings-store",
25737
26116
  capScope: "system",
@@ -25774,6 +26153,12 @@ Object.freeze({
25774
26153
  addonId: null,
25775
26154
  access: "create"
25776
26155
  },
26156
+ "settingsStore.updateWhere": {
26157
+ capName: "settings-store",
26158
+ capScope: "system",
26159
+ addonId: null,
26160
+ access: "create"
26161
+ },
25777
26162
  "smtpProvider.getStatus": {
25778
26163
  capName: "smtp-provider",
25779
26164
  capScope: "system",
@@ -27675,7 +28060,7 @@ var ALEXA_FALLBACK_ENCODE_PROFILE = {
27675
28060
  * Throws `ALEXA_NO_SOURCE_FOR_PROFILE` if the slot has no source assigned.
27676
28061
  */
27677
28062
  async function getOrSpawnAlexaDerivedBroker(opts) {
27678
- const slot = (await opts.api.streamBroker.getProfileSlotsForDevice.query({ deviceId: opts.deviceId })).find((s) => s.profile === opts.sourceProfile);
28063
+ const slot = (await opts.api.streamBroker.listAllProfileSlots.query()).find((s) => s.deviceId === opts.deviceId && s.profile === opts.sourceProfile);
27679
28064
  if (slot?.sourceCamStreamId == null) throw new Error(`ALEXA_NO_SOURCE_FOR_PROFILE: profile=${opts.sourceProfile} deviceId=${opts.deviceId}`);
27680
28065
  const camStreamId = `derived:${computeAlexaDerivedName(opts.deviceId, opts.encodeProfile)}`;
27681
28066
  await opts.api.streamBroker.publishCameraStream.mutate({