@camstack/addon-export-alexa 1.2.9 → 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.
@@ -1,6 +1,6 @@
1
1
  import * as crypto$1 from "node:crypto";
2
2
  import { createHash } from "node:crypto";
3
- //#region ../types/dist/event-category-Bz24uP1U.mjs
3
+ //#region ../types/dist/event-category-41fKf-q9.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -60,6 +60,26 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
60
60
  */
61
61
  EventCategory["AddonRetryScheduled"] = "addon.retry-scheduled";
62
62
  /**
63
+ * A liveness invariant of this node is false — it has no devices, every
64
+ * camera is offline, or a camera that was recording has stopped producing
65
+ * segments. Emitted by the `liveness-monitor` builtin, once per fault (the
66
+ * `findingId` is stable across ticks), only after its boot grace period.
67
+ * AlertCenter raises a persistent operator-visible alert.
68
+ *
69
+ * It exists because on 2026-08-03 the hub ran four hours with zero devices
70
+ * and zero recordings while every surface stayed quiet.
71
+ *
72
+ * Payload: `{ findingId, severity, title, message, deviceId? }`.
73
+ */
74
+ EventCategory["SystemLivenessFailed"] = "system.liveness-failed";
75
+ /**
76
+ * A previously reported liveness fault is true again. AlertCenter dismisses
77
+ * the matching `SystemLivenessFailed` alert.
78
+ *
79
+ * Payload: `{ findingId }`.
80
+ */
81
+ EventCategory["SystemLivenessRecovered"] = "system.liveness-recovered";
82
+ /**
63
83
  * Monitor is attempting to reload a failed addon NOW. UI uses this
64
84
  * to show a spinner during the retry attempt. Same transient nature
65
85
  * as AddonRetryScheduled.
@@ -7450,14 +7470,7 @@ var RecordingConfigSchema = object({
7450
7470
  * windows only — existing sheets are immutable, and each window's index
7451
7471
  * carries its own tile dims so mixed-preset history renders correctly.
7452
7472
  */
7453
- scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
7454
- /**
7455
- * OPT-IN thumbnail-strip generation for this camera: every keyframe of the
7456
- * low recording saved as a JPEG (the fast-drag scrub depth), a derived
7457
- * cache that eviction reclaims with the footage. Absent/false = no strips
7458
- * are written and scrub reads exact keyframes at every velocity.
7459
- */
7460
- stripsEnabled: boolean().optional()
7473
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7461
7474
  }).strict();
7462
7475
  /**
7463
7476
  * Ops-log — the durable, append-only operations audit shared by the
@@ -7519,7 +7532,7 @@ var OpsLogQueryInputSchema = object({
7519
7532
  /**
7520
7533
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
7521
7534
  *
7522
- * One shape shared by the recorder's `relocateFootage` (segments + strips) and
7535
+ * One shape shared by the recorder's `relocateFootage` (segments) and
7523
7536
  * pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
7524
7537
  * page renders both movers with one component. Jobs are in-RAM (a restart
7525
7538
  * forgets them — re-running is safe by construction: copy-if-absent, delete
@@ -7541,7 +7554,7 @@ var RelocateJobSchema = object({
7541
7554
  toLocationId: string(),
7542
7555
  /** Scoped device, or null = every device. */
7543
7556
  deviceId: number().nullable(),
7544
- /** What the job moves (owner-addon specific: segments/strips or media). */
7557
+ /** What the job moves (owner-addon specific: segments or media). */
7545
7558
  entities: array(string()),
7546
7559
  filesMoved: number().int(),
7547
7560
  bytesMoved: number().int(),
@@ -7555,7 +7568,7 @@ var RelocateFootageInputSchema = object({
7555
7568
  deviceId: number().optional(),
7556
7569
  fromLocationId: string(),
7557
7570
  toLocationId: string(),
7558
- entities: array(_enum(["segments", "strips"])).optional(),
7571
+ entities: array(_enum(["segments"])).optional(),
7559
7572
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7560
7573
  * never allowed to starve live writers. */
7561
7574
  throttleMbps: number().min(1).max(1e3).optional()
@@ -9292,11 +9305,13 @@ var NcZoneConditionSchema = object({
9292
9305
  /** Quantifier over `ids` — at least one / every one visited. */
9293
9306
  match: _enum(["any", "all"]).default("any")
9294
9307
  });
9295
- /**
9296
- * The P1 condition set — a flat AND of groups; absent group = pass;
9297
- * membership lists are OR within the list (spec §2.3).
9298
- */
9299
9308
  var NcConditionsSchema = object({
9309
+ /** Gate on ANOTHER device's current state (the alarm armed, a switch on). */
9310
+ deviceState: object({
9311
+ deviceId: number().int(),
9312
+ /** Any of these matches. */
9313
+ states: array(string().min(1)).min(1)
9314
+ }).optional(),
9300
9315
  /** Device scope — absent = all devices. */
9301
9316
  devices: array(number()).optional(),
9302
9317
  /** Detector class names (any overlap with the record's class set). */
@@ -9497,6 +9512,14 @@ var NcMediaPolicySchema = object({
9497
9512
  clipPreRollSec: number().int().min(0).max(30).optional(),
9498
9513
  clipPostRollSec: number().int().min(0).max(30).optional(),
9499
9514
  /**
9515
+ * Playback rate of the attached gif / clip. Absent = 2x.
9516
+ *
9517
+ * A notification clip is GLANCED at on a lock screen, not watched: at real
9518
+ * time an eight-second passage is eight seconds of the recipient's attention
9519
+ * and twice the bytes. 1 is real time for the operator who wants it.
9520
+ */
9521
+ clipSpeed: number().min(1).max(8).optional(),
9522
+ /**
9500
9523
  * Which stream profile the footage is cut from. Absent = the CHEAPEST
9501
9524
  * assigned profile: a notification is watched on a phone, so the 4K
9502
9525
  * rendition would burn CPU to produce a file the client downscales anyway.
@@ -9568,7 +9591,21 @@ var NcRuleInputSchema = object({
9568
9591
  * behaviour, visible to all, read-only in the viewer). Present = personal
9569
9592
  * rule owned by this userId. Server-stamped; never trusted from a client.
9570
9593
  */
9571
- ownerUserId: string().optional()
9594
+ ownerUserId: string().optional(),
9595
+ /**
9596
+ * May a non-admin snooze this rule for EVERYONE, not just themselves?
9597
+ *
9598
+ * A snooze is personal by default — it silences the person who set it. This
9599
+ * opts THIS rule into the "the gardener is here all afternoon" case, where
9600
+ * silencing the camera for the whole household is legitimate. It silences
9601
+ * other people, so it is off unless a rule deliberately allows it.
9602
+ *
9603
+ * `.optional()`, deliberately NOT `.default()`: a Zod default does not run on
9604
+ * the addon cap path (three production failures in one day), so absent is
9605
+ * read as `false` by {@link canSetGlobal} in the engine. Admins are not bound
9606
+ * by this flag — see the scope rules on that function.
9607
+ */
9608
+ snoozeAllowGlobal: boolean().optional()
9572
9609
  });
9573
9610
  /**
9574
9611
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -9639,7 +9676,8 @@ var NcConditionDescriptorSchema = object({
9639
9676
  "packagePhase",
9640
9677
  "crossingSelect",
9641
9678
  "polygonDraw",
9642
- "occupancy"
9679
+ "occupancy",
9680
+ "deviceState"
9643
9681
  ]),
9644
9682
  operator: _enum([
9645
9683
  "in",
@@ -9653,7 +9691,28 @@ var NcConditionDescriptorSchema = object({
9653
9691
  /** Which delivery kinds the condition applies to. */
9654
9692
  appliesTo: array(NcDeliverySchema),
9655
9693
  phase: string(),
9656
- description: string().optional()
9694
+ description: string().optional(),
9695
+ /**
9696
+ * The CHOICES for a single-choice widget (`sourceSelect`, `crossingSelect`,
9697
+ * `packagePhase`, …), served with the descriptor.
9698
+ *
9699
+ * Before this the descriptor said which widget to render and not what to put
9700
+ * in it, so every option list lived in three places: this file's enums, the
9701
+ * admin's `NC_*_OPTIONS` and the viewer's `NC_*_VALUES`. That triple mirror
9702
+ * is the drift that emptied the viewer's rule editor on 2026-08-04 — the app
9703
+ * mirrors the cap by hand, so it is only ever as current as its last build.
9704
+ *
9705
+ * With the options on the wire, a condition of an EXISTING `valueType` costs
9706
+ * zero client changes. Clients keep a local fallback for an older hub that
9707
+ * does not send them; absent here is "use your own list", not "no choices".
9708
+ */
9709
+ options: array(object({
9710
+ /** Written to the rule verbatim. `''` means the ABSENT state. */
9711
+ value: string(),
9712
+ label: string(),
9713
+ /** What THIS choice matches — shown one at a time, under the control. */
9714
+ hint: string().optional()
9715
+ })).readonly().optional()
9657
9716
  });
9658
9717
  /**
9659
9718
  * The delivery lifecycle status of a history row — a straight read of the
@@ -9738,6 +9797,74 @@ var NcHistoryFilterSchema = object({
9738
9797
  until: number().optional(),
9739
9798
  limit: number().int().min(1).max(500).default(100)
9740
9799
  });
9800
+ /**
9801
+ * What a snooze covers. Broader scopes win when several overlap, so one window
9802
+ * leaves ONE digest rather than a rule snooze and a whole-feed snooze both
9803
+ * summarising the same silence.
9804
+ */
9805
+ var NcSnoozeScopeSchema = _enum([
9806
+ "rule",
9807
+ "device",
9808
+ "all"
9809
+ ]);
9810
+ /**
9811
+ * Client-authored snooze. The server stamps `userId`, `startedAt` and
9812
+ * `expiresAt` — a DURATION is sent rather than an instant so a client with a
9813
+ * skewed clock cannot author a window that is already over, or never ends.
9814
+ */
9815
+ var NcSnoozeInputSchema = object({
9816
+ scope: NcSnoozeScopeSchema,
9817
+ /** Required when `scope: 'rule'` — a scoped snooze with no id matches
9818
+ * NOTHING rather than degrading to "everything". */
9819
+ ruleId: string().optional(),
9820
+ /** Required when `scope: 'device'`. */
9821
+ deviceId: number().int().optional(),
9822
+ durationMinutes: number().int().min(1).max(1440),
9823
+ /**
9824
+ * Silence this for EVERY recipient, not just the caller. Permission is
9825
+ * checked server-side (the rule's `snoozeAllowGlobal`, or admin for the
9826
+ * broader scopes). Absent = personal.
9827
+ */
9828
+ global: boolean().optional(),
9829
+ /**
9830
+ * Deliver a summary of what was suppressed when the window ends. Absent =
9831
+ * ON: someone silencing a nuisance camera wants it off, someone silencing a
9832
+ * SECURITY camera wants to know what they missed, and choosing "off" for
9833
+ * everybody is how a snooze becomes an outage. Resolved to a concrete
9834
+ * boolean by the server at create time — never left to a Zod default, which
9835
+ * does not run on the addon cap path.
9836
+ */
9837
+ summary: boolean().optional()
9838
+ });
9839
+ /** A persisted snooze window. */
9840
+ var NcSnoozeSchema = object({
9841
+ id: string(),
9842
+ /** Who set it. Also who it silences, unless `global`. */
9843
+ userId: string(),
9844
+ scope: NcSnoozeScopeSchema,
9845
+ ruleId: string().optional(),
9846
+ deviceId: number().int().optional(),
9847
+ startedAt: number(),
9848
+ /** Exclusive: at exactly this instant the snooze is over. Expiry is a
9849
+ * COMPARISON, not a job — no sweeper can leave the operator silenced. */
9850
+ expiresAt: number(),
9851
+ global: boolean(),
9852
+ summary: boolean(),
9853
+ /** When the end-of-window digest went out. Absent = not sent (yet, or the
9854
+ * window has not closed, or `summary` is false). */
9855
+ digestSentAt: number().optional()
9856
+ });
9857
+ object({
9858
+ snoozeId: string(),
9859
+ targetId: string(),
9860
+ ruleId: string(),
9861
+ ruleName: string(),
9862
+ deviceId: number().int(),
9863
+ /** How many notifications this snooze hid for that pair. */
9864
+ count: number().int(),
9865
+ firstAt: number(),
9866
+ lastAt: number()
9867
+ });
9741
9868
  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 }), {
9742
9869
  kind: "mutation",
9743
9870
  auth: "admin",
@@ -9767,7 +9894,13 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
9767
9894
  }), method(object({}), object({
9768
9895
  catalog: array(NcConditionDescriptorSchema),
9769
9896
  taxonomy: NcTaxonomySchema.optional()
9770
- })), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" });
9897
+ })), 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 }), {
9898
+ kind: "mutation",
9899
+ caller: "required"
9900
+ }), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
9901
+ kind: "mutation",
9902
+ caller: "required"
9903
+ });
9771
9904
  /**
9772
9905
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
9773
9906
  *
@@ -10515,7 +10648,15 @@ method(object({
10515
10648
  format: _enum(["gif", "mp4"]).default("gif"),
10516
10649
  maxWidth: number().int().min(120).max(1920).default(480),
10517
10650
  /** GIF only — MP4 keeps the source cadence. */
10518
- fps: number().int().min(1).max(15).default(5)
10651
+ fps: number().int().min(1).max(15).default(5),
10652
+ /**
10653
+ * Playback rate. A notification clip is GLANCED at on a lock screen,
10654
+ * not watched, so 2x is the default: the recipient sees the whole
10655
+ * passage in half the time and the GIF is half the bytes. `1` is real
10656
+ * time. Applies to MP4 as well — the operator set a speed, not a GIF
10657
+ * speed.
10658
+ */
10659
+ speed: number().min(1).max(8).default(2)
10519
10660
  }), object({
10520
10661
  base64: string(),
10521
10662
  mime: string(),
@@ -15301,6 +15442,210 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15301
15442
  kind: "mutation",
15302
15443
  auth: "admin"
15303
15444
  });
15445
+ /**
15446
+ * Query filter for settings-store collections.
15447
+ */
15448
+ var QueryFilterSchema = object({
15449
+ where: record(string(), unknown()).optional(),
15450
+ whereIn: record(string(), array(unknown())).optional(),
15451
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
15452
+ orderBy: object({
15453
+ field: string(),
15454
+ direction: _enum(["asc", "desc"])
15455
+ }).optional(),
15456
+ limit: number().optional(),
15457
+ offset: number().optional()
15458
+ });
15459
+ /**
15460
+ * The predicate half of a filter, for BULK MUTATIONS.
15461
+ *
15462
+ * Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
15463
+ * meaning for a statement that rewrites a set, and accepting them would invite
15464
+ * a caller to believe `limit` bounds the damage. Every field is optional here
15465
+ * only so the shape stays composable — the implementation REJECTS a filter
15466
+ * that compiles to no predicate, because that is the whole collection.
15467
+ */
15468
+ var MutationFilterSchema = object({
15469
+ where: record(string(), unknown()).optional(),
15470
+ whereIn: record(string(), array(unknown())).optional(),
15471
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
15472
+ });
15473
+ /** A single stored record: `{ id, data }`. */
15474
+ var SettingsRecordSchema = object({
15475
+ id: string(),
15476
+ data: record(string(), unknown())
15477
+ });
15478
+ /**
15479
+ * Column declaration for a structured (SQL-backed) collection.
15480
+ *
15481
+ * Logical types — the backend translates each to the matching SQLite
15482
+ * storage class and handles per-type marshaling:
15483
+ * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
15484
+ * - `JSON` — TEXT under the hood; serialised on write, parsed on read
15485
+ * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
15486
+ */
15487
+ var CollectionColumnSchema = object({
15488
+ name: string(),
15489
+ type: _enum([
15490
+ "TEXT",
15491
+ "INTEGER",
15492
+ "REAL",
15493
+ "JSON",
15494
+ "BOOLEAN"
15495
+ ]),
15496
+ primaryKey: boolean().optional(),
15497
+ notNull: boolean().optional(),
15498
+ unique: boolean().optional(),
15499
+ /**
15500
+ * Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
15501
+ * columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
15502
+ * collection surface simply cannot express their existing tables — which is
15503
+ * why they were still on the uncapped `table*` API.
15504
+ */
15505
+ defaultValue: union([
15506
+ string(),
15507
+ number(),
15508
+ boolean()
15509
+ ]).optional()
15510
+ });
15511
+ var CollectionIndexSchema = object({
15512
+ name: string(),
15513
+ columns: array(string()).readonly(),
15514
+ unique: boolean().optional()
15515
+ });
15516
+ method(object({
15517
+ namespace: string().optional(),
15518
+ collection: string(),
15519
+ key: string()
15520
+ }), unknown()), method(object({
15521
+ namespace: string().optional(),
15522
+ collection: string(),
15523
+ key: string(),
15524
+ value: unknown()
15525
+ }), _void(), { kind: "mutation" }), method(object({
15526
+ namespace: string().optional(),
15527
+ collection: string(),
15528
+ filter: QueryFilterSchema.optional()
15529
+ }), array(SettingsRecordSchema).readonly()), method(object({
15530
+ namespace: string().optional(),
15531
+ collection: string(),
15532
+ record: SettingsRecordSchema
15533
+ }), _void(), { kind: "mutation" }), method(object({
15534
+ namespace: string().optional(),
15535
+ collection: string(),
15536
+ id: string(),
15537
+ data: record(string(), unknown())
15538
+ }), _void(), { kind: "mutation" }), method(object({
15539
+ namespace: string().optional(),
15540
+ collection: string(),
15541
+ key: string()
15542
+ }), _void(), { kind: "mutation" }), method(object({
15543
+ namespace: string().optional(),
15544
+ collection: string(),
15545
+ filter: MutationFilterSchema
15546
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
15547
+ namespace: string().optional(),
15548
+ collection: string(),
15549
+ filter: MutationFilterSchema,
15550
+ data: record(string(), unknown())
15551
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
15552
+ namespace: string().optional(),
15553
+ collection: string(),
15554
+ filter: QueryFilterSchema.optional()
15555
+ }), number()), method(object({
15556
+ namespace: string().optional(),
15557
+ collection: string(),
15558
+ field: string(),
15559
+ bucketSize: number().int().positive(),
15560
+ origin: number().int(),
15561
+ filter: QueryFilterSchema.optional()
15562
+ }), array(object({
15563
+ bucket: number().int(),
15564
+ count: number().int()
15565
+ })).readonly()), method(object({
15566
+ namespace: string().optional(),
15567
+ collection: string()
15568
+ }), boolean()), method(object({
15569
+ namespace: string().optional(),
15570
+ collection: string(),
15571
+ columns: array(CollectionColumnSchema).readonly(),
15572
+ indexes: array(CollectionIndexSchema).readonly().optional()
15573
+ }), _void(), { kind: "mutation" });
15574
+ /**
15575
+ * What one engine says about itself. The orchestrator uses `kind` to pick
15576
+ * a registrant for a collection; `engineId` is what a log line names when
15577
+ * a call is routed or refused.
15578
+ */
15579
+ var EngineInfoSchema = object({
15580
+ engineId: string(),
15581
+ /**
15582
+ * `relational` — rows, columns, indexes, the surface `settings-store`
15583
+ * has always described. `vector` — an embedding store answering
15584
+ * similarity queries. A registrant declares exactly one; an engine that
15585
+ * does both registers twice, because "both" would make the routing
15586
+ * decision ambiguous at exactly the point it must not be.
15587
+ */
15588
+ kind: _enum(["relational", "vector"]),
15589
+ displayName: string()
15590
+ });
15591
+ method(_void(), EngineInfoSchema), method(object({
15592
+ namespace: string().optional(),
15593
+ collection: string(),
15594
+ key: string()
15595
+ }), unknown()), method(object({
15596
+ namespace: string().optional(),
15597
+ collection: string(),
15598
+ key: string(),
15599
+ value: unknown()
15600
+ }), _void(), { kind: "mutation" }), method(object({
15601
+ namespace: string().optional(),
15602
+ collection: string(),
15603
+ filter: QueryFilterSchema.optional()
15604
+ }), array(SettingsRecordSchema).readonly()), method(object({
15605
+ namespace: string().optional(),
15606
+ collection: string(),
15607
+ record: SettingsRecordSchema
15608
+ }), _void(), { kind: "mutation" }), method(object({
15609
+ namespace: string().optional(),
15610
+ collection: string(),
15611
+ id: string(),
15612
+ data: record(string(), unknown())
15613
+ }), _void(), { kind: "mutation" }), method(object({
15614
+ namespace: string().optional(),
15615
+ collection: string(),
15616
+ key: string()
15617
+ }), _void(), { kind: "mutation" }), method(object({
15618
+ namespace: string().optional(),
15619
+ collection: string(),
15620
+ filter: MutationFilterSchema
15621
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
15622
+ namespace: string().optional(),
15623
+ collection: string(),
15624
+ filter: MutationFilterSchema,
15625
+ data: record(string(), unknown())
15626
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
15627
+ namespace: string().optional(),
15628
+ collection: string(),
15629
+ filter: QueryFilterSchema.optional()
15630
+ }), number()), method(object({
15631
+ namespace: string().optional(),
15632
+ collection: string(),
15633
+ field: string(),
15634
+ bucketSize: number().int().positive(),
15635
+ origin: number().int(),
15636
+ filter: QueryFilterSchema.optional()
15637
+ }), array(object({
15638
+ bucket: number().int(),
15639
+ count: number().int()
15640
+ })).readonly()), method(object({
15641
+ namespace: string().optional(),
15642
+ collection: string()
15643
+ }), boolean()), method(object({
15644
+ namespace: string().optional(),
15645
+ collection: string(),
15646
+ columns: array(CollectionColumnSchema).readonly(),
15647
+ indexes: array(CollectionIndexSchema).readonly().optional()
15648
+ }), _void(), { kind: "mutation" });
15304
15649
  DeviceType.Camera;
15305
15650
  /**
15306
15651
  * `device-adoption` — generic discovery + adoption surface,
@@ -18564,6 +18909,28 @@ var ServerUpdateStateSchema = _enum([
18564
18909
  "pending-restart",
18565
18910
  "awaiting-confirmation"
18566
18911
  ]);
18912
+ var ImageContractSchema = object({
18913
+ state: _enum([
18914
+ "in-sync",
18915
+ "behind-patch",
18916
+ "behind-series",
18917
+ "ahead",
18918
+ "unknown"
18919
+ ]),
18920
+ /** The baked seed closure version — the image/app-bundle fingerprint. */
18921
+ seedVersion: string().nullable(),
18922
+ /** Best-known version the deployment contract delivers today. */
18923
+ contractVersion: string().nullable(),
18924
+ /**
18925
+ * Where `contractVersion` came from: a real registry check (`registry`), or
18926
+ * the node's own running version (`running` — a node can never run code
18927
+ * newer than the newest release, so `seed < running` proves image staleness
18928
+ * even before any registry check has run).
18929
+ */
18930
+ contractSource: _enum(["registry", "running"]).nullable(),
18931
+ /** One operator-grade sentence: this node runs image X; the contract says Y. */
18932
+ message: string()
18933
+ });
18567
18934
  var ServerRollbackInfoSchema = object({
18568
18935
  /** The version that failed (or was manually rolled back). */
18569
18936
  fromVersion: string(),
@@ -18600,7 +18967,12 @@ var ServerPackageStatusSchema = object({
18600
18967
  * versions are being IGNORED. Surfaced as a warning in the UI.
18601
18968
  */
18602
18969
  stateFileCorrupt: boolean(),
18603
- lastCheckedAtMs: number().nullable()
18970
+ lastCheckedAtMs: number().nullable(),
18971
+ /**
18972
+ * Seed-vs-contract verdict (see {@link ImageContractSchema}). Optional for
18973
+ * version skew: an older provider's payload simply omits it.
18974
+ */
18975
+ imageContract: ImageContractSchema.optional()
18604
18976
  });
18605
18977
  var ServerUpdateCheckResultSchema = object({
18606
18978
  packageName: string(),
@@ -18635,101 +19007,6 @@ version: string().optional() }), ServerUpdateActionResultSchema, {
18635
19007
  auth: "admin"
18636
19008
  });
18637
19009
  /**
18638
- * Query filter for settings-store collections.
18639
- */
18640
- var QueryFilterSchema = object({
18641
- where: record(string(), unknown()).optional(),
18642
- whereIn: record(string(), array(unknown())).optional(),
18643
- whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
18644
- orderBy: object({
18645
- field: string(),
18646
- direction: _enum(["asc", "desc"])
18647
- }).optional(),
18648
- limit: number().optional(),
18649
- offset: number().optional()
18650
- });
18651
- /** A single stored record: `{ id, data }`. */
18652
- var SettingsRecordSchema = object({
18653
- id: string(),
18654
- data: record(string(), unknown())
18655
- });
18656
- /**
18657
- * Column declaration for a structured (SQL-backed) collection.
18658
- *
18659
- * Logical types — the backend translates each to the matching SQLite
18660
- * storage class and handles per-type marshaling:
18661
- * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
18662
- * - `JSON` — TEXT under the hood; serialised on write, parsed on read
18663
- * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
18664
- */
18665
- var CollectionColumnSchema = object({
18666
- name: string(),
18667
- type: _enum([
18668
- "TEXT",
18669
- "INTEGER",
18670
- "REAL",
18671
- "JSON",
18672
- "BOOLEAN"
18673
- ]),
18674
- primaryKey: boolean().optional(),
18675
- notNull: boolean().optional(),
18676
- unique: boolean().optional()
18677
- });
18678
- var CollectionIndexSchema = object({
18679
- name: string(),
18680
- columns: array(string()).readonly(),
18681
- unique: boolean().optional()
18682
- });
18683
- method(object({
18684
- namespace: string().optional(),
18685
- collection: string(),
18686
- key: string()
18687
- }), unknown()), method(object({
18688
- namespace: string().optional(),
18689
- collection: string(),
18690
- key: string(),
18691
- value: unknown()
18692
- }), _void(), { kind: "mutation" }), method(object({
18693
- namespace: string().optional(),
18694
- collection: string(),
18695
- filter: QueryFilterSchema.optional()
18696
- }), array(SettingsRecordSchema).readonly()), method(object({
18697
- namespace: string().optional(),
18698
- collection: string(),
18699
- record: SettingsRecordSchema
18700
- }), _void(), { kind: "mutation" }), method(object({
18701
- namespace: string().optional(),
18702
- collection: string(),
18703
- id: string(),
18704
- data: record(string(), unknown())
18705
- }), _void(), { kind: "mutation" }), method(object({
18706
- namespace: string().optional(),
18707
- collection: string(),
18708
- key: string()
18709
- }), _void(), { kind: "mutation" }), method(object({
18710
- namespace: string().optional(),
18711
- collection: string(),
18712
- filter: QueryFilterSchema.optional()
18713
- }), number()), method(object({
18714
- namespace: string().optional(),
18715
- collection: string(),
18716
- field: string(),
18717
- bucketSize: number().int().positive(),
18718
- origin: number().int(),
18719
- filter: QueryFilterSchema.optional()
18720
- }), array(object({
18721
- bucket: number().int(),
18722
- count: number().int()
18723
- })).readonly()), method(object({
18724
- namespace: string().optional(),
18725
- collection: string()
18726
- }), boolean()), method(object({
18727
- namespace: string().optional(),
18728
- collection: string(),
18729
- columns: array(CollectionColumnSchema).readonly(),
18730
- indexes: array(CollectionIndexSchema).readonly().optional()
18731
- }), _void(), { kind: "mutation" });
18732
- /**
18733
19010
  * `smtp-provider` — pluggable email delivery surface.
18734
19011
  *
18735
19012
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
@@ -22628,6 +22905,84 @@ Object.freeze({
22628
22905
  addonId: null,
22629
22906
  access: "view"
22630
22907
  },
22908
+ "dataStoreProvider.count": {
22909
+ capName: "data-store-provider",
22910
+ capScope: "system",
22911
+ addonId: null,
22912
+ access: "view"
22913
+ },
22914
+ "dataStoreProvider.declareCollection": {
22915
+ capName: "data-store-provider",
22916
+ capScope: "system",
22917
+ addonId: null,
22918
+ access: "create"
22919
+ },
22920
+ "dataStoreProvider.delete": {
22921
+ capName: "data-store-provider",
22922
+ capScope: "system",
22923
+ addonId: null,
22924
+ access: "delete"
22925
+ },
22926
+ "dataStoreProvider.deleteWhere": {
22927
+ capName: "data-store-provider",
22928
+ capScope: "system",
22929
+ addonId: null,
22930
+ access: "delete"
22931
+ },
22932
+ "dataStoreProvider.get": {
22933
+ capName: "data-store-provider",
22934
+ capScope: "system",
22935
+ addonId: null,
22936
+ access: "view"
22937
+ },
22938
+ "dataStoreProvider.getEngineInfo": {
22939
+ capName: "data-store-provider",
22940
+ capScope: "system",
22941
+ addonId: null,
22942
+ access: "view"
22943
+ },
22944
+ "dataStoreProvider.histogram": {
22945
+ capName: "data-store-provider",
22946
+ capScope: "system",
22947
+ addonId: null,
22948
+ access: "view"
22949
+ },
22950
+ "dataStoreProvider.insert": {
22951
+ capName: "data-store-provider",
22952
+ capScope: "system",
22953
+ addonId: null,
22954
+ access: "create"
22955
+ },
22956
+ "dataStoreProvider.isEmpty": {
22957
+ capName: "data-store-provider",
22958
+ capScope: "system",
22959
+ addonId: null,
22960
+ access: "view"
22961
+ },
22962
+ "dataStoreProvider.query": {
22963
+ capName: "data-store-provider",
22964
+ capScope: "system",
22965
+ addonId: null,
22966
+ access: "view"
22967
+ },
22968
+ "dataStoreProvider.set": {
22969
+ capName: "data-store-provider",
22970
+ capScope: "system",
22971
+ addonId: null,
22972
+ access: "create"
22973
+ },
22974
+ "dataStoreProvider.update": {
22975
+ capName: "data-store-provider",
22976
+ capScope: "system",
22977
+ addonId: null,
22978
+ access: "create"
22979
+ },
22980
+ "dataStoreProvider.updateWhere": {
22981
+ capName: "data-store-provider",
22982
+ capScope: "system",
22983
+ addonId: null,
22984
+ access: "create"
22985
+ },
22631
22986
  "dayNight.getOptions": {
22632
22987
  capName: "day-night",
22633
22988
  capScope: "device",
@@ -24422,12 +24777,24 @@ Object.freeze({
24422
24777
  addonId: null,
24423
24778
  access: "create"
24424
24779
  },
24780
+ "notificationRules.cancelSnooze": {
24781
+ capName: "notification-rules",
24782
+ capScope: "system",
24783
+ addonId: null,
24784
+ access: "create"
24785
+ },
24425
24786
  "notificationRules.createRule": {
24426
24787
  capName: "notification-rules",
24427
24788
  capScope: "system",
24428
24789
  addonId: null,
24429
24790
  access: "create"
24430
24791
  },
24792
+ "notificationRules.createSnooze": {
24793
+ capName: "notification-rules",
24794
+ capScope: "system",
24795
+ addonId: null,
24796
+ access: "create"
24797
+ },
24431
24798
  "notificationRules.deleteRule": {
24432
24799
  capName: "notification-rules",
24433
24800
  capScope: "system",
@@ -24458,6 +24825,12 @@ Object.freeze({
24458
24825
  addonId: null,
24459
24826
  access: "view"
24460
24827
  },
24828
+ "notificationRules.listSnoozes": {
24829
+ capName: "notification-rules",
24830
+ capScope: "system",
24831
+ addonId: null,
24832
+ access: "view"
24833
+ },
24461
24834
  "notificationRules.setRuleEnabled": {
24462
24835
  capName: "notification-rules",
24463
24836
  capScope: "system",
@@ -25706,6 +26079,12 @@ Object.freeze({
25706
26079
  addonId: null,
25707
26080
  access: "delete"
25708
26081
  },
26082
+ "settingsStore.deleteWhere": {
26083
+ capName: "settings-store",
26084
+ capScope: "system",
26085
+ addonId: null,
26086
+ access: "delete"
26087
+ },
25709
26088
  "settingsStore.get": {
25710
26089
  capName: "settings-store",
25711
26090
  capScope: "system",
@@ -25748,6 +26127,12 @@ Object.freeze({
25748
26127
  addonId: null,
25749
26128
  access: "create"
25750
26129
  },
26130
+ "settingsStore.updateWhere": {
26131
+ capName: "settings-store",
26132
+ capScope: "system",
26133
+ addonId: null,
26134
+ access: "create"
26135
+ },
25751
26136
  "smtpProvider.getStatus": {
25752
26137
  capName: "smtp-provider",
25753
26138
  capScope: "system",
@@ -27649,7 +28034,7 @@ var ALEXA_FALLBACK_ENCODE_PROFILE = {
27649
28034
  * Throws `ALEXA_NO_SOURCE_FOR_PROFILE` if the slot has no source assigned.
27650
28035
  */
27651
28036
  async function getOrSpawnAlexaDerivedBroker(opts) {
27652
- const slot = (await opts.api.streamBroker.getProfileSlotsForDevice.query({ deviceId: opts.deviceId })).find((s) => s.profile === opts.sourceProfile);
28037
+ const slot = (await opts.api.streamBroker.listAllProfileSlots.query()).find((s) => s.deviceId === opts.deviceId && s.profile === opts.sourceProfile);
27653
28038
  if (slot?.sourceCamStreamId == null) throw new Error(`ALEXA_NO_SOURCE_FOR_PROFILE: profile=${opts.sourceProfile} deviceId=${opts.deviceId}`);
27654
28039
  const camStreamId = `derived:${computeAlexaDerivedName(opts.deviceId, opts.encodeProfile)}`;
27655
28040
  await opts.api.streamBroker.publishCameraStream.mutate({