@camstack/addon-provider-homeassistant 1.2.10 → 1.2.11

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.
Files changed (3) hide show
  1. package/dist/addon.js +348 -109
  2. package/dist/addon.mjs +348 -109
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let node_crypto = require("node:crypto");
3
3
  let node_zlib = require("node:zlib");
4
- //#region ../types/dist/event-category-Bz24uP1U.mjs
4
+ //#region ../types/dist/event-category-41fKf-q9.mjs
5
5
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
6
6
  EventCategory["SystemBoot"] = "system.boot";
7
7
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -61,6 +61,26 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
61
61
  */
62
62
  EventCategory["AddonRetryScheduled"] = "addon.retry-scheduled";
63
63
  /**
64
+ * A liveness invariant of this node is false — it has no devices, every
65
+ * camera is offline, or a camera that was recording has stopped producing
66
+ * segments. Emitted by the `liveness-monitor` builtin, once per fault (the
67
+ * `findingId` is stable across ticks), only after its boot grace period.
68
+ * AlertCenter raises a persistent operator-visible alert.
69
+ *
70
+ * It exists because on 2026-08-03 the hub ran four hours with zero devices
71
+ * and zero recordings while every surface stayed quiet.
72
+ *
73
+ * Payload: `{ findingId, severity, title, message, deviceId? }`.
74
+ */
75
+ EventCategory["SystemLivenessFailed"] = "system.liveness-failed";
76
+ /**
77
+ * A previously reported liveness fault is true again. AlertCenter dismisses
78
+ * the matching `SystemLivenessFailed` alert.
79
+ *
80
+ * Payload: `{ findingId }`.
81
+ */
82
+ EventCategory["SystemLivenessRecovered"] = "system.liveness-recovered";
83
+ /**
64
84
  * Monitor is attempting to reload a failed addon NOW. UI uses this
65
85
  * to show a spinner during the retry attempt. Same transient nature
66
86
  * as AddonRetryScheduled.
@@ -7444,14 +7464,7 @@ var RecordingConfigSchema = object({
7444
7464
  * windows only — existing sheets are immutable, and each window's index
7445
7465
  * carries its own tile dims so mixed-preset history renders correctly.
7446
7466
  */
7447
- scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
7448
- /**
7449
- * OPT-IN thumbnail-strip generation for this camera: every keyframe of the
7450
- * low recording saved as a JPEG (the fast-drag scrub depth), a derived
7451
- * cache that eviction reclaims with the footage. Absent/false = no strips
7452
- * are written and scrub reads exact keyframes at every velocity.
7453
- */
7454
- stripsEnabled: boolean().optional()
7467
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7455
7468
  }).strict();
7456
7469
  /**
7457
7470
  * Ops-log — the durable, append-only operations audit shared by the
@@ -7513,7 +7526,7 @@ var OpsLogQueryInputSchema = object({
7513
7526
  /**
7514
7527
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
7515
7528
  *
7516
- * One shape shared by the recorder's `relocateFootage` (segments + strips) and
7529
+ * One shape shared by the recorder's `relocateFootage` (segments) and
7517
7530
  * pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
7518
7531
  * page renders both movers with one component. Jobs are in-RAM (a restart
7519
7532
  * forgets them — re-running is safe by construction: copy-if-absent, delete
@@ -7535,7 +7548,7 @@ var RelocateJobSchema = object({
7535
7548
  toLocationId: string(),
7536
7549
  /** Scoped device, or null = every device. */
7537
7550
  deviceId: number().nullable(),
7538
- /** What the job moves (owner-addon specific: segments/strips or media). */
7551
+ /** What the job moves (owner-addon specific: segments or media). */
7539
7552
  entities: array(string()),
7540
7553
  filesMoved: number().int(),
7541
7554
  bytesMoved: number().int(),
@@ -7549,7 +7562,7 @@ var RelocateFootageInputSchema = object({
7549
7562
  deviceId: number().optional(),
7550
7563
  fromLocationId: string(),
7551
7564
  toLocationId: string(),
7552
- entities: array(_enum(["segments", "strips"])).optional(),
7565
+ entities: array(_enum(["segments"])).optional(),
7553
7566
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7554
7567
  * never allowed to starve live writers. */
7555
7568
  throttleMbps: number().min(1).max(1e3).optional()
@@ -18512,6 +18525,210 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
18512
18525
  kind: "mutation",
18513
18526
  auth: "admin"
18514
18527
  });
18528
+ /**
18529
+ * Query filter for settings-store collections.
18530
+ */
18531
+ var QueryFilterSchema = object({
18532
+ where: record(string(), unknown()).optional(),
18533
+ whereIn: record(string(), array(unknown())).optional(),
18534
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
18535
+ orderBy: object({
18536
+ field: string(),
18537
+ direction: _enum(["asc", "desc"])
18538
+ }).optional(),
18539
+ limit: number().optional(),
18540
+ offset: number().optional()
18541
+ });
18542
+ /**
18543
+ * The predicate half of a filter, for BULK MUTATIONS.
18544
+ *
18545
+ * Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
18546
+ * meaning for a statement that rewrites a set, and accepting them would invite
18547
+ * a caller to believe `limit` bounds the damage. Every field is optional here
18548
+ * only so the shape stays composable — the implementation REJECTS a filter
18549
+ * that compiles to no predicate, because that is the whole collection.
18550
+ */
18551
+ var MutationFilterSchema = object({
18552
+ where: record(string(), unknown()).optional(),
18553
+ whereIn: record(string(), array(unknown())).optional(),
18554
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
18555
+ });
18556
+ /** A single stored record: `{ id, data }`. */
18557
+ var SettingsRecordSchema = object({
18558
+ id: string(),
18559
+ data: record(string(), unknown())
18560
+ });
18561
+ /**
18562
+ * Column declaration for a structured (SQL-backed) collection.
18563
+ *
18564
+ * Logical types — the backend translates each to the matching SQLite
18565
+ * storage class and handles per-type marshaling:
18566
+ * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
18567
+ * - `JSON` — TEXT under the hood; serialised on write, parsed on read
18568
+ * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
18569
+ */
18570
+ var CollectionColumnSchema = object({
18571
+ name: string(),
18572
+ type: _enum([
18573
+ "TEXT",
18574
+ "INTEGER",
18575
+ "REAL",
18576
+ "JSON",
18577
+ "BOOLEAN"
18578
+ ]),
18579
+ primaryKey: boolean().optional(),
18580
+ notNull: boolean().optional(),
18581
+ unique: boolean().optional(),
18582
+ /**
18583
+ * Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
18584
+ * columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
18585
+ * collection surface simply cannot express their existing tables — which is
18586
+ * why they were still on the uncapped `table*` API.
18587
+ */
18588
+ defaultValue: union([
18589
+ string(),
18590
+ number(),
18591
+ boolean()
18592
+ ]).optional()
18593
+ });
18594
+ var CollectionIndexSchema = object({
18595
+ name: string(),
18596
+ columns: array(string()).readonly(),
18597
+ unique: boolean().optional()
18598
+ });
18599
+ method(object({
18600
+ namespace: string().optional(),
18601
+ collection: string(),
18602
+ key: string()
18603
+ }), unknown()), method(object({
18604
+ namespace: string().optional(),
18605
+ collection: string(),
18606
+ key: string(),
18607
+ value: unknown()
18608
+ }), _void(), { kind: "mutation" }), method(object({
18609
+ namespace: string().optional(),
18610
+ collection: string(),
18611
+ filter: QueryFilterSchema.optional()
18612
+ }), array(SettingsRecordSchema).readonly()), method(object({
18613
+ namespace: string().optional(),
18614
+ collection: string(),
18615
+ record: SettingsRecordSchema
18616
+ }), _void(), { kind: "mutation" }), method(object({
18617
+ namespace: string().optional(),
18618
+ collection: string(),
18619
+ id: string(),
18620
+ data: record(string(), unknown())
18621
+ }), _void(), { kind: "mutation" }), method(object({
18622
+ namespace: string().optional(),
18623
+ collection: string(),
18624
+ key: string()
18625
+ }), _void(), { kind: "mutation" }), method(object({
18626
+ namespace: string().optional(),
18627
+ collection: string(),
18628
+ filter: MutationFilterSchema
18629
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
18630
+ namespace: string().optional(),
18631
+ collection: string(),
18632
+ filter: MutationFilterSchema,
18633
+ data: record(string(), unknown())
18634
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
18635
+ namespace: string().optional(),
18636
+ collection: string(),
18637
+ filter: QueryFilterSchema.optional()
18638
+ }), number()), method(object({
18639
+ namespace: string().optional(),
18640
+ collection: string(),
18641
+ field: string(),
18642
+ bucketSize: number().int().positive(),
18643
+ origin: number().int(),
18644
+ filter: QueryFilterSchema.optional()
18645
+ }), array(object({
18646
+ bucket: number().int(),
18647
+ count: number().int()
18648
+ })).readonly()), method(object({
18649
+ namespace: string().optional(),
18650
+ collection: string()
18651
+ }), boolean()), method(object({
18652
+ namespace: string().optional(),
18653
+ collection: string(),
18654
+ columns: array(CollectionColumnSchema).readonly(),
18655
+ indexes: array(CollectionIndexSchema).readonly().optional()
18656
+ }), _void(), { kind: "mutation" });
18657
+ /**
18658
+ * What one engine says about itself. The orchestrator uses `kind` to pick
18659
+ * a registrant for a collection; `engineId` is what a log line names when
18660
+ * a call is routed or refused.
18661
+ */
18662
+ var EngineInfoSchema = object({
18663
+ engineId: string(),
18664
+ /**
18665
+ * `relational` — rows, columns, indexes, the surface `settings-store`
18666
+ * has always described. `vector` — an embedding store answering
18667
+ * similarity queries. A registrant declares exactly one; an engine that
18668
+ * does both registers twice, because "both" would make the routing
18669
+ * decision ambiguous at exactly the point it must not be.
18670
+ */
18671
+ kind: _enum(["relational", "vector"]),
18672
+ displayName: string()
18673
+ });
18674
+ method(_void(), EngineInfoSchema), method(object({
18675
+ namespace: string().optional(),
18676
+ collection: string(),
18677
+ key: string()
18678
+ }), unknown()), method(object({
18679
+ namespace: string().optional(),
18680
+ collection: string(),
18681
+ key: string(),
18682
+ value: unknown()
18683
+ }), _void(), { kind: "mutation" }), method(object({
18684
+ namespace: string().optional(),
18685
+ collection: string(),
18686
+ filter: QueryFilterSchema.optional()
18687
+ }), array(SettingsRecordSchema).readonly()), method(object({
18688
+ namespace: string().optional(),
18689
+ collection: string(),
18690
+ record: SettingsRecordSchema
18691
+ }), _void(), { kind: "mutation" }), method(object({
18692
+ namespace: string().optional(),
18693
+ collection: string(),
18694
+ id: string(),
18695
+ data: record(string(), unknown())
18696
+ }), _void(), { kind: "mutation" }), method(object({
18697
+ namespace: string().optional(),
18698
+ collection: string(),
18699
+ key: string()
18700
+ }), _void(), { kind: "mutation" }), method(object({
18701
+ namespace: string().optional(),
18702
+ collection: string(),
18703
+ filter: MutationFilterSchema
18704
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
18705
+ namespace: string().optional(),
18706
+ collection: string(),
18707
+ filter: MutationFilterSchema,
18708
+ data: record(string(), unknown())
18709
+ }), object({ updated: number().int() }), { 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" });
18515
18732
  DeviceType.Camera;
18516
18733
  /**
18517
18734
  * `device-adoption` — generic discovery + adoption surface,
@@ -21775,6 +21992,28 @@ var ServerUpdateStateSchema = _enum([
21775
21992
  "pending-restart",
21776
21993
  "awaiting-confirmation"
21777
21994
  ]);
21995
+ var ImageContractSchema = object({
21996
+ state: _enum([
21997
+ "in-sync",
21998
+ "behind-patch",
21999
+ "behind-series",
22000
+ "ahead",
22001
+ "unknown"
22002
+ ]),
22003
+ /** The baked seed closure version — the image/app-bundle fingerprint. */
22004
+ seedVersion: string().nullable(),
22005
+ /** Best-known version the deployment contract delivers today. */
22006
+ contractVersion: string().nullable(),
22007
+ /**
22008
+ * Where `contractVersion` came from: a real registry check (`registry`), or
22009
+ * the node's own running version (`running` — a node can never run code
22010
+ * newer than the newest release, so `seed < running` proves image staleness
22011
+ * even before any registry check has run).
22012
+ */
22013
+ contractSource: _enum(["registry", "running"]).nullable(),
22014
+ /** One operator-grade sentence: this node runs image X; the contract says Y. */
22015
+ message: string()
22016
+ });
21778
22017
  var ServerRollbackInfoSchema = object({
21779
22018
  /** The version that failed (or was manually rolled back). */
21780
22019
  fromVersion: string(),
@@ -21811,7 +22050,12 @@ var ServerPackageStatusSchema = object({
21811
22050
  * versions are being IGNORED. Surfaced as a warning in the UI.
21812
22051
  */
21813
22052
  stateFileCorrupt: boolean(),
21814
- lastCheckedAtMs: number().nullable()
22053
+ lastCheckedAtMs: number().nullable(),
22054
+ /**
22055
+ * Seed-vs-contract verdict (see {@link ImageContractSchema}). Optional for
22056
+ * version skew: an older provider's payload simply omits it.
22057
+ */
22058
+ imageContract: ImageContractSchema.optional()
21815
22059
  });
21816
22060
  var ServerUpdateCheckResultSchema = object({
21817
22061
  packageName: string(),
@@ -21846,101 +22090,6 @@ version: string().optional() }), ServerUpdateActionResultSchema, {
21846
22090
  auth: "admin"
21847
22091
  });
21848
22092
  /**
21849
- * Query filter for settings-store collections.
21850
- */
21851
- var QueryFilterSchema = object({
21852
- where: record(string(), unknown()).optional(),
21853
- whereIn: record(string(), array(unknown())).optional(),
21854
- whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
21855
- orderBy: object({
21856
- field: string(),
21857
- direction: _enum(["asc", "desc"])
21858
- }).optional(),
21859
- limit: number().optional(),
21860
- offset: number().optional()
21861
- });
21862
- /** A single stored record: `{ id, data }`. */
21863
- var SettingsRecordSchema = object({
21864
- id: string(),
21865
- data: record(string(), unknown())
21866
- });
21867
- /**
21868
- * Column declaration for a structured (SQL-backed) collection.
21869
- *
21870
- * Logical types — the backend translates each to the matching SQLite
21871
- * storage class and handles per-type marshaling:
21872
- * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
21873
- * - `JSON` — TEXT under the hood; serialised on write, parsed on read
21874
- * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
21875
- */
21876
- var CollectionColumnSchema = object({
21877
- name: string(),
21878
- type: _enum([
21879
- "TEXT",
21880
- "INTEGER",
21881
- "REAL",
21882
- "JSON",
21883
- "BOOLEAN"
21884
- ]),
21885
- primaryKey: boolean().optional(),
21886
- notNull: boolean().optional(),
21887
- unique: boolean().optional()
21888
- });
21889
- var CollectionIndexSchema = object({
21890
- name: string(),
21891
- columns: array(string()).readonly(),
21892
- unique: boolean().optional()
21893
- });
21894
- method(object({
21895
- namespace: string().optional(),
21896
- collection: string(),
21897
- key: string()
21898
- }), unknown()), method(object({
21899
- namespace: string().optional(),
21900
- collection: string(),
21901
- key: string(),
21902
- value: unknown()
21903
- }), _void(), { kind: "mutation" }), method(object({
21904
- namespace: string().optional(),
21905
- collection: string(),
21906
- filter: QueryFilterSchema.optional()
21907
- }), array(SettingsRecordSchema).readonly()), method(object({
21908
- namespace: string().optional(),
21909
- collection: string(),
21910
- record: SettingsRecordSchema
21911
- }), _void(), { kind: "mutation" }), method(object({
21912
- namespace: string().optional(),
21913
- collection: string(),
21914
- id: string(),
21915
- data: record(string(), unknown())
21916
- }), _void(), { kind: "mutation" }), method(object({
21917
- namespace: string().optional(),
21918
- collection: string(),
21919
- key: string()
21920
- }), _void(), { kind: "mutation" }), method(object({
21921
- namespace: string().optional(),
21922
- collection: string(),
21923
- filter: QueryFilterSchema.optional()
21924
- }), number()), method(object({
21925
- namespace: string().optional(),
21926
- collection: string(),
21927
- field: string(),
21928
- bucketSize: number().int().positive(),
21929
- origin: number().int(),
21930
- filter: QueryFilterSchema.optional()
21931
- }), array(object({
21932
- bucket: number().int(),
21933
- count: number().int()
21934
- })).readonly()), method(object({
21935
- namespace: string().optional(),
21936
- collection: string()
21937
- }), boolean()), method(object({
21938
- namespace: string().optional(),
21939
- collection: string(),
21940
- columns: array(CollectionColumnSchema).readonly(),
21941
- indexes: array(CollectionIndexSchema).readonly().optional()
21942
- }), _void(), { kind: "mutation" });
21943
- /**
21944
22093
  * `smtp-provider` — pluggable email delivery surface.
21945
22094
  *
21946
22095
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
@@ -25928,6 +26077,84 @@ Object.freeze({
25928
26077
  addonId: null,
25929
26078
  access: "view"
25930
26079
  },
26080
+ "dataStoreProvider.count": {
26081
+ capName: "data-store-provider",
26082
+ capScope: "system",
26083
+ addonId: null,
26084
+ access: "view"
26085
+ },
26086
+ "dataStoreProvider.declareCollection": {
26087
+ capName: "data-store-provider",
26088
+ capScope: "system",
26089
+ addonId: null,
26090
+ access: "create"
26091
+ },
26092
+ "dataStoreProvider.delete": {
26093
+ capName: "data-store-provider",
26094
+ capScope: "system",
26095
+ addonId: null,
26096
+ access: "delete"
26097
+ },
26098
+ "dataStoreProvider.deleteWhere": {
26099
+ capName: "data-store-provider",
26100
+ capScope: "system",
26101
+ addonId: null,
26102
+ access: "delete"
26103
+ },
26104
+ "dataStoreProvider.get": {
26105
+ capName: "data-store-provider",
26106
+ capScope: "system",
26107
+ addonId: null,
26108
+ access: "view"
26109
+ },
26110
+ "dataStoreProvider.getEngineInfo": {
26111
+ capName: "data-store-provider",
26112
+ capScope: "system",
26113
+ addonId: null,
26114
+ access: "view"
26115
+ },
26116
+ "dataStoreProvider.histogram": {
26117
+ capName: "data-store-provider",
26118
+ capScope: "system",
26119
+ addonId: null,
26120
+ access: "view"
26121
+ },
26122
+ "dataStoreProvider.insert": {
26123
+ capName: "data-store-provider",
26124
+ capScope: "system",
26125
+ addonId: null,
26126
+ access: "create"
26127
+ },
26128
+ "dataStoreProvider.isEmpty": {
26129
+ capName: "data-store-provider",
26130
+ capScope: "system",
26131
+ addonId: null,
26132
+ access: "view"
26133
+ },
26134
+ "dataStoreProvider.query": {
26135
+ capName: "data-store-provider",
26136
+ capScope: "system",
26137
+ addonId: null,
26138
+ access: "view"
26139
+ },
26140
+ "dataStoreProvider.set": {
26141
+ capName: "data-store-provider",
26142
+ capScope: "system",
26143
+ addonId: null,
26144
+ access: "create"
26145
+ },
26146
+ "dataStoreProvider.update": {
26147
+ capName: "data-store-provider",
26148
+ capScope: "system",
26149
+ addonId: null,
26150
+ access: "create"
26151
+ },
26152
+ "dataStoreProvider.updateWhere": {
26153
+ capName: "data-store-provider",
26154
+ capScope: "system",
26155
+ addonId: null,
26156
+ access: "create"
26157
+ },
25931
26158
  "dayNight.getOptions": {
25932
26159
  capName: "day-night",
25933
26160
  capScope: "device",
@@ -29006,6 +29233,12 @@ Object.freeze({
29006
29233
  addonId: null,
29007
29234
  access: "delete"
29008
29235
  },
29236
+ "settingsStore.deleteWhere": {
29237
+ capName: "settings-store",
29238
+ capScope: "system",
29239
+ addonId: null,
29240
+ access: "delete"
29241
+ },
29009
29242
  "settingsStore.get": {
29010
29243
  capName: "settings-store",
29011
29244
  capScope: "system",
@@ -29048,6 +29281,12 @@ Object.freeze({
29048
29281
  addonId: null,
29049
29282
  access: "create"
29050
29283
  },
29284
+ "settingsStore.updateWhere": {
29285
+ capName: "settings-store",
29286
+ capScope: "system",
29287
+ addonId: null,
29288
+ access: "create"
29289
+ },
29051
29290
  "smtpProvider.getStatus": {
29052
29291
  capName: "smtp-provider",
29053
29292
  capScope: "system",
@@ -36532,7 +36771,7 @@ function createHaIconRouteProvider() {
36532
36771
  /** The single kind this provider contributes to the shared catalog. */
36533
36772
  var HA_NOTIFICATION_KIND = "homeassistant";
36534
36773
  /** addonId-namespaced settings-store collection holding HA notify targets. */
36535
- var HA_TARGETS_COLLECTION = "ha-notification-targets";
36774
+ var HA_TARGETS_COLLECTION = "provider-homeassistant:ha-notification-targets";
36536
36775
  function haConfigSchema() {
36537
36776
  return { sections: [{
36538
36777
  id: "connection",
package/dist/addon.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
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.
@@ -7443,14 +7463,7 @@ var RecordingConfigSchema = object({
7443
7463
  * windows only — existing sheets are immutable, and each window's index
7444
7464
  * carries its own tile dims so mixed-preset history renders correctly.
7445
7465
  */
7446
- scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
7447
- /**
7448
- * OPT-IN thumbnail-strip generation for this camera: every keyframe of the
7449
- * low recording saved as a JPEG (the fast-drag scrub depth), a derived
7450
- * cache that eviction reclaims with the footage. Absent/false = no strips
7451
- * are written and scrub reads exact keyframes at every velocity.
7452
- */
7453
- stripsEnabled: boolean().optional()
7466
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7454
7467
  }).strict();
7455
7468
  /**
7456
7469
  * Ops-log — the durable, append-only operations audit shared by the
@@ -7512,7 +7525,7 @@ var OpsLogQueryInputSchema = object({
7512
7525
  /**
7513
7526
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
7514
7527
  *
7515
- * One shape shared by the recorder's `relocateFootage` (segments + strips) and
7528
+ * One shape shared by the recorder's `relocateFootage` (segments) and
7516
7529
  * pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
7517
7530
  * page renders both movers with one component. Jobs are in-RAM (a restart
7518
7531
  * forgets them — re-running is safe by construction: copy-if-absent, delete
@@ -7534,7 +7547,7 @@ var RelocateJobSchema = object({
7534
7547
  toLocationId: string(),
7535
7548
  /** Scoped device, or null = every device. */
7536
7549
  deviceId: number().nullable(),
7537
- /** What the job moves (owner-addon specific: segments/strips or media). */
7550
+ /** What the job moves (owner-addon specific: segments or media). */
7538
7551
  entities: array(string()),
7539
7552
  filesMoved: number().int(),
7540
7553
  bytesMoved: number().int(),
@@ -7548,7 +7561,7 @@ var RelocateFootageInputSchema = object({
7548
7561
  deviceId: number().optional(),
7549
7562
  fromLocationId: string(),
7550
7563
  toLocationId: string(),
7551
- entities: array(_enum(["segments", "strips"])).optional(),
7564
+ entities: array(_enum(["segments"])).optional(),
7552
7565
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7553
7566
  * never allowed to starve live writers. */
7554
7567
  throttleMbps: number().min(1).max(1e3).optional()
@@ -18511,6 +18524,210 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
18511
18524
  kind: "mutation",
18512
18525
  auth: "admin"
18513
18526
  });
18527
+ /**
18528
+ * Query filter for settings-store collections.
18529
+ */
18530
+ var QueryFilterSchema = object({
18531
+ where: record(string(), unknown()).optional(),
18532
+ whereIn: record(string(), array(unknown())).optional(),
18533
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
18534
+ orderBy: object({
18535
+ field: string(),
18536
+ direction: _enum(["asc", "desc"])
18537
+ }).optional(),
18538
+ limit: number().optional(),
18539
+ offset: number().optional()
18540
+ });
18541
+ /**
18542
+ * The predicate half of a filter, for BULK MUTATIONS.
18543
+ *
18544
+ * Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
18545
+ * meaning for a statement that rewrites a set, and accepting them would invite
18546
+ * a caller to believe `limit` bounds the damage. Every field is optional here
18547
+ * only so the shape stays composable — the implementation REJECTS a filter
18548
+ * that compiles to no predicate, because that is the whole collection.
18549
+ */
18550
+ var MutationFilterSchema = object({
18551
+ where: record(string(), unknown()).optional(),
18552
+ whereIn: record(string(), array(unknown())).optional(),
18553
+ whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
18554
+ });
18555
+ /** A single stored record: `{ id, data }`. */
18556
+ var SettingsRecordSchema = object({
18557
+ id: string(),
18558
+ data: record(string(), unknown())
18559
+ });
18560
+ /**
18561
+ * Column declaration for a structured (SQL-backed) collection.
18562
+ *
18563
+ * Logical types — the backend translates each to the matching SQLite
18564
+ * storage class and handles per-type marshaling:
18565
+ * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
18566
+ * - `JSON` — TEXT under the hood; serialised on write, parsed on read
18567
+ * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
18568
+ */
18569
+ var CollectionColumnSchema = object({
18570
+ name: string(),
18571
+ type: _enum([
18572
+ "TEXT",
18573
+ "INTEGER",
18574
+ "REAL",
18575
+ "JSON",
18576
+ "BOOLEAN"
18577
+ ]),
18578
+ primaryKey: boolean().optional(),
18579
+ notNull: boolean().optional(),
18580
+ unique: boolean().optional(),
18581
+ /**
18582
+ * Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
18583
+ * columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
18584
+ * collection surface simply cannot express their existing tables — which is
18585
+ * why they were still on the uncapped `table*` API.
18586
+ */
18587
+ defaultValue: union([
18588
+ string(),
18589
+ number(),
18590
+ boolean()
18591
+ ]).optional()
18592
+ });
18593
+ var CollectionIndexSchema = object({
18594
+ name: string(),
18595
+ columns: array(string()).readonly(),
18596
+ unique: boolean().optional()
18597
+ });
18598
+ method(object({
18599
+ namespace: string().optional(),
18600
+ collection: string(),
18601
+ key: string()
18602
+ }), unknown()), method(object({
18603
+ namespace: string().optional(),
18604
+ collection: string(),
18605
+ key: string(),
18606
+ value: unknown()
18607
+ }), _void(), { kind: "mutation" }), method(object({
18608
+ namespace: string().optional(),
18609
+ collection: string(),
18610
+ filter: QueryFilterSchema.optional()
18611
+ }), array(SettingsRecordSchema).readonly()), method(object({
18612
+ namespace: string().optional(),
18613
+ collection: string(),
18614
+ record: SettingsRecordSchema
18615
+ }), _void(), { kind: "mutation" }), method(object({
18616
+ namespace: string().optional(),
18617
+ collection: string(),
18618
+ id: string(),
18619
+ data: record(string(), unknown())
18620
+ }), _void(), { kind: "mutation" }), method(object({
18621
+ namespace: string().optional(),
18622
+ collection: string(),
18623
+ key: string()
18624
+ }), _void(), { kind: "mutation" }), method(object({
18625
+ namespace: string().optional(),
18626
+ collection: string(),
18627
+ filter: MutationFilterSchema
18628
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
18629
+ namespace: string().optional(),
18630
+ collection: string(),
18631
+ filter: MutationFilterSchema,
18632
+ data: record(string(), unknown())
18633
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
18634
+ namespace: string().optional(),
18635
+ collection: string(),
18636
+ filter: QueryFilterSchema.optional()
18637
+ }), number()), method(object({
18638
+ namespace: string().optional(),
18639
+ collection: string(),
18640
+ field: string(),
18641
+ bucketSize: number().int().positive(),
18642
+ origin: number().int(),
18643
+ filter: QueryFilterSchema.optional()
18644
+ }), array(object({
18645
+ bucket: number().int(),
18646
+ count: number().int()
18647
+ })).readonly()), method(object({
18648
+ namespace: string().optional(),
18649
+ collection: string()
18650
+ }), boolean()), method(object({
18651
+ namespace: string().optional(),
18652
+ collection: string(),
18653
+ columns: array(CollectionColumnSchema).readonly(),
18654
+ indexes: array(CollectionIndexSchema).readonly().optional()
18655
+ }), _void(), { kind: "mutation" });
18656
+ /**
18657
+ * What one engine says about itself. The orchestrator uses `kind` to pick
18658
+ * a registrant for a collection; `engineId` is what a log line names when
18659
+ * a call is routed or refused.
18660
+ */
18661
+ var EngineInfoSchema = object({
18662
+ engineId: string(),
18663
+ /**
18664
+ * `relational` — rows, columns, indexes, the surface `settings-store`
18665
+ * has always described. `vector` — an embedding store answering
18666
+ * similarity queries. A registrant declares exactly one; an engine that
18667
+ * does both registers twice, because "both" would make the routing
18668
+ * decision ambiguous at exactly the point it must not be.
18669
+ */
18670
+ kind: _enum(["relational", "vector"]),
18671
+ displayName: string()
18672
+ });
18673
+ method(_void(), EngineInfoSchema), method(object({
18674
+ namespace: string().optional(),
18675
+ collection: string(),
18676
+ key: string()
18677
+ }), unknown()), method(object({
18678
+ namespace: string().optional(),
18679
+ collection: string(),
18680
+ key: string(),
18681
+ value: unknown()
18682
+ }), _void(), { kind: "mutation" }), method(object({
18683
+ namespace: string().optional(),
18684
+ collection: string(),
18685
+ filter: QueryFilterSchema.optional()
18686
+ }), array(SettingsRecordSchema).readonly()), method(object({
18687
+ namespace: string().optional(),
18688
+ collection: string(),
18689
+ record: SettingsRecordSchema
18690
+ }), _void(), { kind: "mutation" }), method(object({
18691
+ namespace: string().optional(),
18692
+ collection: string(),
18693
+ id: string(),
18694
+ data: record(string(), unknown())
18695
+ }), _void(), { kind: "mutation" }), method(object({
18696
+ namespace: string().optional(),
18697
+ collection: string(),
18698
+ key: string()
18699
+ }), _void(), { kind: "mutation" }), method(object({
18700
+ namespace: string().optional(),
18701
+ collection: string(),
18702
+ filter: MutationFilterSchema
18703
+ }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
18704
+ namespace: string().optional(),
18705
+ collection: string(),
18706
+ filter: MutationFilterSchema,
18707
+ data: record(string(), unknown())
18708
+ }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
18709
+ namespace: string().optional(),
18710
+ collection: string(),
18711
+ filter: QueryFilterSchema.optional()
18712
+ }), number()), method(object({
18713
+ namespace: string().optional(),
18714
+ collection: string(),
18715
+ field: string(),
18716
+ bucketSize: number().int().positive(),
18717
+ origin: number().int(),
18718
+ filter: QueryFilterSchema.optional()
18719
+ }), array(object({
18720
+ bucket: number().int(),
18721
+ count: number().int()
18722
+ })).readonly()), method(object({
18723
+ namespace: string().optional(),
18724
+ collection: string()
18725
+ }), boolean()), method(object({
18726
+ namespace: string().optional(),
18727
+ collection: string(),
18728
+ columns: array(CollectionColumnSchema).readonly(),
18729
+ indexes: array(CollectionIndexSchema).readonly().optional()
18730
+ }), _void(), { kind: "mutation" });
18514
18731
  DeviceType.Camera;
18515
18732
  /**
18516
18733
  * `device-adoption` — generic discovery + adoption surface,
@@ -21774,6 +21991,28 @@ var ServerUpdateStateSchema = _enum([
21774
21991
  "pending-restart",
21775
21992
  "awaiting-confirmation"
21776
21993
  ]);
21994
+ var ImageContractSchema = object({
21995
+ state: _enum([
21996
+ "in-sync",
21997
+ "behind-patch",
21998
+ "behind-series",
21999
+ "ahead",
22000
+ "unknown"
22001
+ ]),
22002
+ /** The baked seed closure version — the image/app-bundle fingerprint. */
22003
+ seedVersion: string().nullable(),
22004
+ /** Best-known version the deployment contract delivers today. */
22005
+ contractVersion: string().nullable(),
22006
+ /**
22007
+ * Where `contractVersion` came from: a real registry check (`registry`), or
22008
+ * the node's own running version (`running` — a node can never run code
22009
+ * newer than the newest release, so `seed < running` proves image staleness
22010
+ * even before any registry check has run).
22011
+ */
22012
+ contractSource: _enum(["registry", "running"]).nullable(),
22013
+ /** One operator-grade sentence: this node runs image X; the contract says Y. */
22014
+ message: string()
22015
+ });
21777
22016
  var ServerRollbackInfoSchema = object({
21778
22017
  /** The version that failed (or was manually rolled back). */
21779
22018
  fromVersion: string(),
@@ -21810,7 +22049,12 @@ var ServerPackageStatusSchema = object({
21810
22049
  * versions are being IGNORED. Surfaced as a warning in the UI.
21811
22050
  */
21812
22051
  stateFileCorrupt: boolean(),
21813
- lastCheckedAtMs: number().nullable()
22052
+ lastCheckedAtMs: number().nullable(),
22053
+ /**
22054
+ * Seed-vs-contract verdict (see {@link ImageContractSchema}). Optional for
22055
+ * version skew: an older provider's payload simply omits it.
22056
+ */
22057
+ imageContract: ImageContractSchema.optional()
21814
22058
  });
21815
22059
  var ServerUpdateCheckResultSchema = object({
21816
22060
  packageName: string(),
@@ -21845,101 +22089,6 @@ version: string().optional() }), ServerUpdateActionResultSchema, {
21845
22089
  auth: "admin"
21846
22090
  });
21847
22091
  /**
21848
- * Query filter for settings-store collections.
21849
- */
21850
- var QueryFilterSchema = object({
21851
- where: record(string(), unknown()).optional(),
21852
- whereIn: record(string(), array(unknown())).optional(),
21853
- whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
21854
- orderBy: object({
21855
- field: string(),
21856
- direction: _enum(["asc", "desc"])
21857
- }).optional(),
21858
- limit: number().optional(),
21859
- offset: number().optional()
21860
- });
21861
- /** A single stored record: `{ id, data }`. */
21862
- var SettingsRecordSchema = object({
21863
- id: string(),
21864
- data: record(string(), unknown())
21865
- });
21866
- /**
21867
- * Column declaration for a structured (SQL-backed) collection.
21868
- *
21869
- * Logical types — the backend translates each to the matching SQLite
21870
- * storage class and handles per-type marshaling:
21871
- * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
21872
- * - `JSON` — TEXT under the hood; serialised on write, parsed on read
21873
- * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
21874
- */
21875
- var CollectionColumnSchema = object({
21876
- name: string(),
21877
- type: _enum([
21878
- "TEXT",
21879
- "INTEGER",
21880
- "REAL",
21881
- "JSON",
21882
- "BOOLEAN"
21883
- ]),
21884
- primaryKey: boolean().optional(),
21885
- notNull: boolean().optional(),
21886
- unique: boolean().optional()
21887
- });
21888
- var CollectionIndexSchema = object({
21889
- name: string(),
21890
- columns: array(string()).readonly(),
21891
- unique: boolean().optional()
21892
- });
21893
- method(object({
21894
- namespace: string().optional(),
21895
- collection: string(),
21896
- key: string()
21897
- }), unknown()), method(object({
21898
- namespace: string().optional(),
21899
- collection: string(),
21900
- key: string(),
21901
- value: unknown()
21902
- }), _void(), { kind: "mutation" }), method(object({
21903
- namespace: string().optional(),
21904
- collection: string(),
21905
- filter: QueryFilterSchema.optional()
21906
- }), array(SettingsRecordSchema).readonly()), method(object({
21907
- namespace: string().optional(),
21908
- collection: string(),
21909
- record: SettingsRecordSchema
21910
- }), _void(), { kind: "mutation" }), method(object({
21911
- namespace: string().optional(),
21912
- collection: string(),
21913
- id: string(),
21914
- data: record(string(), unknown())
21915
- }), _void(), { kind: "mutation" }), method(object({
21916
- namespace: string().optional(),
21917
- collection: string(),
21918
- key: string()
21919
- }), _void(), { kind: "mutation" }), method(object({
21920
- namespace: string().optional(),
21921
- collection: string(),
21922
- filter: QueryFilterSchema.optional()
21923
- }), number()), method(object({
21924
- namespace: string().optional(),
21925
- collection: string(),
21926
- field: string(),
21927
- bucketSize: number().int().positive(),
21928
- origin: number().int(),
21929
- filter: QueryFilterSchema.optional()
21930
- }), array(object({
21931
- bucket: number().int(),
21932
- count: number().int()
21933
- })).readonly()), method(object({
21934
- namespace: string().optional(),
21935
- collection: string()
21936
- }), boolean()), method(object({
21937
- namespace: string().optional(),
21938
- collection: string(),
21939
- columns: array(CollectionColumnSchema).readonly(),
21940
- indexes: array(CollectionIndexSchema).readonly().optional()
21941
- }), _void(), { kind: "mutation" });
21942
- /**
21943
22092
  * `smtp-provider` — pluggable email delivery surface.
21944
22093
  *
21945
22094
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
@@ -25927,6 +26076,84 @@ Object.freeze({
25927
26076
  addonId: null,
25928
26077
  access: "view"
25929
26078
  },
26079
+ "dataStoreProvider.count": {
26080
+ capName: "data-store-provider",
26081
+ capScope: "system",
26082
+ addonId: null,
26083
+ access: "view"
26084
+ },
26085
+ "dataStoreProvider.declareCollection": {
26086
+ capName: "data-store-provider",
26087
+ capScope: "system",
26088
+ addonId: null,
26089
+ access: "create"
26090
+ },
26091
+ "dataStoreProvider.delete": {
26092
+ capName: "data-store-provider",
26093
+ capScope: "system",
26094
+ addonId: null,
26095
+ access: "delete"
26096
+ },
26097
+ "dataStoreProvider.deleteWhere": {
26098
+ capName: "data-store-provider",
26099
+ capScope: "system",
26100
+ addonId: null,
26101
+ access: "delete"
26102
+ },
26103
+ "dataStoreProvider.get": {
26104
+ capName: "data-store-provider",
26105
+ capScope: "system",
26106
+ addonId: null,
26107
+ access: "view"
26108
+ },
26109
+ "dataStoreProvider.getEngineInfo": {
26110
+ capName: "data-store-provider",
26111
+ capScope: "system",
26112
+ addonId: null,
26113
+ access: "view"
26114
+ },
26115
+ "dataStoreProvider.histogram": {
26116
+ capName: "data-store-provider",
26117
+ capScope: "system",
26118
+ addonId: null,
26119
+ access: "view"
26120
+ },
26121
+ "dataStoreProvider.insert": {
26122
+ capName: "data-store-provider",
26123
+ capScope: "system",
26124
+ addonId: null,
26125
+ access: "create"
26126
+ },
26127
+ "dataStoreProvider.isEmpty": {
26128
+ capName: "data-store-provider",
26129
+ capScope: "system",
26130
+ addonId: null,
26131
+ access: "view"
26132
+ },
26133
+ "dataStoreProvider.query": {
26134
+ capName: "data-store-provider",
26135
+ capScope: "system",
26136
+ addonId: null,
26137
+ access: "view"
26138
+ },
26139
+ "dataStoreProvider.set": {
26140
+ capName: "data-store-provider",
26141
+ capScope: "system",
26142
+ addonId: null,
26143
+ access: "create"
26144
+ },
26145
+ "dataStoreProvider.update": {
26146
+ capName: "data-store-provider",
26147
+ capScope: "system",
26148
+ addonId: null,
26149
+ access: "create"
26150
+ },
26151
+ "dataStoreProvider.updateWhere": {
26152
+ capName: "data-store-provider",
26153
+ capScope: "system",
26154
+ addonId: null,
26155
+ access: "create"
26156
+ },
25930
26157
  "dayNight.getOptions": {
25931
26158
  capName: "day-night",
25932
26159
  capScope: "device",
@@ -29005,6 +29232,12 @@ Object.freeze({
29005
29232
  addonId: null,
29006
29233
  access: "delete"
29007
29234
  },
29235
+ "settingsStore.deleteWhere": {
29236
+ capName: "settings-store",
29237
+ capScope: "system",
29238
+ addonId: null,
29239
+ access: "delete"
29240
+ },
29008
29241
  "settingsStore.get": {
29009
29242
  capName: "settings-store",
29010
29243
  capScope: "system",
@@ -29047,6 +29280,12 @@ Object.freeze({
29047
29280
  addonId: null,
29048
29281
  access: "create"
29049
29282
  },
29283
+ "settingsStore.updateWhere": {
29284
+ capName: "settings-store",
29285
+ capScope: "system",
29286
+ addonId: null,
29287
+ access: "create"
29288
+ },
29050
29289
  "smtpProvider.getStatus": {
29051
29290
  capName: "smtp-provider",
29052
29291
  capScope: "system",
@@ -36531,7 +36770,7 @@ function createHaIconRouteProvider() {
36531
36770
  /** The single kind this provider contributes to the shared catalog. */
36532
36771
  var HA_NOTIFICATION_KIND = "homeassistant";
36533
36772
  /** addonId-namespaced settings-store collection holding HA notify targets. */
36534
- var HA_TARGETS_COLLECTION = "ha-notification-targets";
36773
+ var HA_TARGETS_COLLECTION = "provider-homeassistant:ha-notification-targets";
36535
36774
  function haConfigSchema() {
36536
36775
  return { sections: [{
36537
36776
  id: "connection",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",