@camstack/addon-provider-tuya 0.1.12 → 0.1.13

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.
package/dist/addon.js CHANGED
@@ -7362,6 +7362,62 @@ var RecordingConfigSchema = object({
7362
7362
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7363
7363
  });
7364
7364
  /**
7365
+ * Ops-log — the durable, append-only operations audit shared by the
7366
+ * recordings and events management surfaces.
7367
+ *
7368
+ * ONE row shape is reused for both domains so a single "Activity" view can
7369
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7370
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7371
+ * management operation, WHY it ran (reason), and its measurable effect
7372
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7373
+ * never fail the operation it records.
7374
+ */
7375
+ /** Which management domain the operation belongs to. */
7376
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7377
+ /** The kind of management operation performed. */
7378
+ var OpsLogOpSchema = _enum([
7379
+ "prune",
7380
+ "manual-delete",
7381
+ "rescan",
7382
+ "retention-run"
7383
+ ]);
7384
+ /** Why the operation ran. */
7385
+ var OpsLogReasonSchema = _enum([
7386
+ "retention",
7387
+ "quota",
7388
+ "manual",
7389
+ "operator"
7390
+ ]);
7391
+ /** One audit row, shared verbatim by both domains. */
7392
+ var OpsLogEntrySchema = object({
7393
+ /** Unique row id. */
7394
+ id: string(),
7395
+ /** Epoch ms the operation completed. */
7396
+ at: number(),
7397
+ domain: OpsLogDomainSchema,
7398
+ op: OpsLogOpSchema,
7399
+ reason: OpsLogReasonSchema,
7400
+ /** The camera the op targeted; null for a cluster/global op. */
7401
+ deviceId: number().nullable(),
7402
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7403
+ nodeId: string(),
7404
+ /** Buckets / rows deleted (op-specific unit). */
7405
+ itemsAffected: number(),
7406
+ /** Bytes reclaimed by the op (0 when not measurable). */
7407
+ bytesReclaimed: number(),
7408
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7409
+ detail: string().nullable(),
7410
+ /** Who/what triggered the op. */
7411
+ actor: string()
7412
+ });
7413
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7414
+ var OpsLogQueryInputSchema = object({
7415
+ /** Restrict to a single camera; omit for every row. */
7416
+ deviceId: number().optional(),
7417
+ /** Max rows returned, newest-first. */
7418
+ limit: number().int().min(1).max(1e3).optional()
7419
+ });
7420
+ /**
7365
7421
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7366
7422
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7367
7423
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -14825,9 +14881,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
14825
14881
  * `package` backs the package-drop detector — a package zone is a
14826
14882
  * `ZoneRule` on the `'package'` stage referencing drawn polygons
14827
14883
  * (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
14828
- * The orchestrator provider that writes this stage lands in a later
14829
- * slice; until then the mirror carries only `{motion, detection}` and
14830
- * consumers read `package` as absent (treat as `[]`).
14884
+ * The orchestrator provider writes this stage as a first-class slice
14885
+ * (Phase 4): every mutation mirrors the full `{motion, detection,
14886
+ * package}` shape, so consumers read the current package rules directly
14887
+ * off `device.state.zoneRules.value.package`.
14831
14888
  */
14832
14889
  runtimeState: object({
14833
14890
  motion: array(ZoneRuleSchema).readonly(),
@@ -19161,6 +19218,26 @@ var TrackCascadeCountsSchema = object({
19161
19218
  /** Per-track CLIP search vectors removed (best-effort). */
19162
19219
  embeddings: number().int()
19163
19220
  });
19221
+ /** Event-store footprint for one camera. */
19222
+ var EventStoreDeviceFootprintSchema = object({
19223
+ deviceId: number(),
19224
+ /** Persisted event rows (motion + object + audio) for the camera. */
19225
+ rows: number().int(),
19226
+ /** Event-owned media bytes on disk for the camera. */
19227
+ bytes: number().int()
19228
+ });
19229
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
19230
+ var EventStoreFootprintSchema = object({
19231
+ totalRows: number().int(),
19232
+ totalBytes: number().int(),
19233
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
19234
+ });
19235
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
19236
+ var EventPruneCountsSchema = object({
19237
+ motion: number().int(),
19238
+ object: number().int(),
19239
+ audio: number().int()
19240
+ });
19164
19241
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
19165
19242
  deviceId: number(),
19166
19243
  trackId: string()
@@ -19224,6 +19301,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19224
19301
  }), {
19225
19302
  kind: "mutation",
19226
19303
  auth: "admin"
19304
+ }), method(object({}), EventStoreFootprintSchema, {
19305
+ kind: "query",
19306
+ auth: "admin"
19307
+ }), method(object({
19308
+ olderThanMs: number(),
19309
+ reason: OpsLogReasonSchema.optional()
19310
+ }), EventPruneCountsSchema, {
19311
+ kind: "mutation",
19312
+ auth: "admin"
19313
+ }), method(object({ deviceId: number() }), EventPruneCountsSchema, {
19314
+ kind: "mutation",
19315
+ auth: "admin"
19316
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19317
+ kind: "query",
19318
+ auth: "admin"
19227
19319
  }), method(object({
19228
19320
  eventId: string(),
19229
19321
  kind: MediaFileKindEnum.optional()
@@ -22457,13 +22549,29 @@ method(object({
22457
22549
  }), method(object({ deviceId: number() }), RecordingStatusSchema, {
22458
22550
  kind: "mutation",
22459
22551
  auth: "admin"
22460
- }), method(object({ deviceId: number() }), object({
22552
+ }), method(object({
22553
+ deviceId: number(),
22554
+ reason: OpsLogReasonSchema.optional()
22555
+ }), object({
22461
22556
  floorMs: number().nullable(),
22462
22557
  deletedBuckets: number().int(),
22463
22558
  reclaimedBytes: number().int()
22464
22559
  }), {
22465
22560
  kind: "mutation",
22466
22561
  auth: "admin"
22562
+ }), method(object({
22563
+ deviceId: number(),
22564
+ fromMs: number().optional(),
22565
+ toMs: number().optional()
22566
+ }), object({
22567
+ deletedBuckets: number().int(),
22568
+ reclaimedBytes: number().int()
22569
+ }), {
22570
+ kind: "mutation",
22571
+ auth: "admin"
22572
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
22573
+ kind: "query",
22574
+ auth: "admin"
22467
22575
  });
22468
22576
  /**
22469
22577
  * `recordingExport` cap — render a footage time range into a single downloadable
@@ -25585,6 +25693,12 @@ Object.freeze({
25585
25693
  addonId: null,
25586
25694
  access: "delete"
25587
25695
  },
25696
+ "pipelineAnalytics.deleteDeviceEvents": {
25697
+ capName: "pipeline-analytics",
25698
+ capScope: "device",
25699
+ addonId: null,
25700
+ access: "delete"
25701
+ },
25588
25702
  "pipelineAnalytics.deleteTracks": {
25589
25703
  capName: "pipeline-analytics",
25590
25704
  capScope: "device",
@@ -25615,6 +25729,12 @@ Object.freeze({
25615
25729
  addonId: null,
25616
25730
  access: "view"
25617
25731
  },
25732
+ "pipelineAnalytics.getEventStoreFootprint": {
25733
+ capName: "pipeline-analytics",
25734
+ capScope: "device",
25735
+ addonId: null,
25736
+ access: "view"
25737
+ },
25618
25738
  "pipelineAnalytics.getKeyEvents": {
25619
25739
  capName: "pipeline-analytics",
25620
25740
  capScope: "device",
@@ -25657,6 +25777,12 @@ Object.freeze({
25657
25777
  addonId: null,
25658
25778
  access: "view"
25659
25779
  },
25780
+ "pipelineAnalytics.listOpsLog": {
25781
+ capName: "pipeline-analytics",
25782
+ capScope: "device",
25783
+ addonId: null,
25784
+ access: "view"
25785
+ },
25660
25786
  "pipelineAnalytics.listRecentTracks": {
25661
25787
  capName: "pipeline-analytics",
25662
25788
  capScope: "device",
@@ -25669,6 +25795,12 @@ Object.freeze({
25669
25795
  addonId: null,
25670
25796
  access: "view"
25671
25797
  },
25798
+ "pipelineAnalytics.pruneEvents": {
25799
+ capName: "pipeline-analytics",
25800
+ capScope: "device",
25801
+ addonId: null,
25802
+ access: "create"
25803
+ },
25672
25804
  "pipelineAnalytics.pruneEventsBefore": {
25673
25805
  capName: "pipeline-analytics",
25674
25806
  capScope: "device",
@@ -26431,6 +26563,12 @@ Object.freeze({
26431
26563
  addonId: null,
26432
26564
  access: "create"
26433
26565
  },
26566
+ "recording.deleteFootprint": {
26567
+ capName: "recording",
26568
+ capScope: "system",
26569
+ addonId: null,
26570
+ access: "delete"
26571
+ },
26434
26572
  "recording.getAvailability": {
26435
26573
  capName: "recording",
26436
26574
  capScope: "system",
@@ -26461,6 +26599,12 @@ Object.freeze({
26461
26599
  addonId: null,
26462
26600
  access: "view"
26463
26601
  },
26602
+ "recording.listOpsLog": {
26603
+ capName: "recording",
26604
+ capScope: "system",
26605
+ addonId: null,
26606
+ access: "view"
26607
+ },
26464
26608
  "recording.locateSegment": {
26465
26609
  capName: "recording",
26466
26610
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -7361,6 +7361,62 @@ var RecordingConfigSchema = object({
7361
7361
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7362
7362
  });
7363
7363
  /**
7364
+ * Ops-log — the durable, append-only operations audit shared by the
7365
+ * recordings and events management surfaces.
7366
+ *
7367
+ * ONE row shape is reused for both domains so a single "Activity" view can
7368
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7369
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7370
+ * management operation, WHY it ran (reason), and its measurable effect
7371
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7372
+ * never fail the operation it records.
7373
+ */
7374
+ /** Which management domain the operation belongs to. */
7375
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7376
+ /** The kind of management operation performed. */
7377
+ var OpsLogOpSchema = _enum([
7378
+ "prune",
7379
+ "manual-delete",
7380
+ "rescan",
7381
+ "retention-run"
7382
+ ]);
7383
+ /** Why the operation ran. */
7384
+ var OpsLogReasonSchema = _enum([
7385
+ "retention",
7386
+ "quota",
7387
+ "manual",
7388
+ "operator"
7389
+ ]);
7390
+ /** One audit row, shared verbatim by both domains. */
7391
+ var OpsLogEntrySchema = object({
7392
+ /** Unique row id. */
7393
+ id: string(),
7394
+ /** Epoch ms the operation completed. */
7395
+ at: number(),
7396
+ domain: OpsLogDomainSchema,
7397
+ op: OpsLogOpSchema,
7398
+ reason: OpsLogReasonSchema,
7399
+ /** The camera the op targeted; null for a cluster/global op. */
7400
+ deviceId: number().nullable(),
7401
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7402
+ nodeId: string(),
7403
+ /** Buckets / rows deleted (op-specific unit). */
7404
+ itemsAffected: number(),
7405
+ /** Bytes reclaimed by the op (0 when not measurable). */
7406
+ bytesReclaimed: number(),
7407
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7408
+ detail: string().nullable(),
7409
+ /** Who/what triggered the op. */
7410
+ actor: string()
7411
+ });
7412
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7413
+ var OpsLogQueryInputSchema = object({
7414
+ /** Restrict to a single camera; omit for every row. */
7415
+ deviceId: number().optional(),
7416
+ /** Max rows returned, newest-first. */
7417
+ limit: number().int().min(1).max(1e3).optional()
7418
+ });
7419
+ /**
7364
7420
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7365
7421
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7366
7422
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -14824,9 +14880,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
14824
14880
  * `package` backs the package-drop detector — a package zone is a
14825
14881
  * `ZoneRule` on the `'package'` stage referencing drawn polygons
14826
14882
  * (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
14827
- * The orchestrator provider that writes this stage lands in a later
14828
- * slice; until then the mirror carries only `{motion, detection}` and
14829
- * consumers read `package` as absent (treat as `[]`).
14883
+ * The orchestrator provider writes this stage as a first-class slice
14884
+ * (Phase 4): every mutation mirrors the full `{motion, detection,
14885
+ * package}` shape, so consumers read the current package rules directly
14886
+ * off `device.state.zoneRules.value.package`.
14830
14887
  */
14831
14888
  runtimeState: object({
14832
14889
  motion: array(ZoneRuleSchema).readonly(),
@@ -19160,6 +19217,26 @@ var TrackCascadeCountsSchema = object({
19160
19217
  /** Per-track CLIP search vectors removed (best-effort). */
19161
19218
  embeddings: number().int()
19162
19219
  });
19220
+ /** Event-store footprint for one camera. */
19221
+ var EventStoreDeviceFootprintSchema = object({
19222
+ deviceId: number(),
19223
+ /** Persisted event rows (motion + object + audio) for the camera. */
19224
+ rows: number().int(),
19225
+ /** Event-owned media bytes on disk for the camera. */
19226
+ bytes: number().int()
19227
+ });
19228
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
19229
+ var EventStoreFootprintSchema = object({
19230
+ totalRows: number().int(),
19231
+ totalBytes: number().int(),
19232
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
19233
+ });
19234
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
19235
+ var EventPruneCountsSchema = object({
19236
+ motion: number().int(),
19237
+ object: number().int(),
19238
+ audio: number().int()
19239
+ });
19163
19240
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
19164
19241
  deviceId: number(),
19165
19242
  trackId: string()
@@ -19223,6 +19300,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19223
19300
  }), {
19224
19301
  kind: "mutation",
19225
19302
  auth: "admin"
19303
+ }), method(object({}), EventStoreFootprintSchema, {
19304
+ kind: "query",
19305
+ auth: "admin"
19306
+ }), method(object({
19307
+ olderThanMs: number(),
19308
+ reason: OpsLogReasonSchema.optional()
19309
+ }), EventPruneCountsSchema, {
19310
+ kind: "mutation",
19311
+ auth: "admin"
19312
+ }), method(object({ deviceId: number() }), EventPruneCountsSchema, {
19313
+ kind: "mutation",
19314
+ auth: "admin"
19315
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19316
+ kind: "query",
19317
+ auth: "admin"
19226
19318
  }), method(object({
19227
19319
  eventId: string(),
19228
19320
  kind: MediaFileKindEnum.optional()
@@ -22456,13 +22548,29 @@ method(object({
22456
22548
  }), method(object({ deviceId: number() }), RecordingStatusSchema, {
22457
22549
  kind: "mutation",
22458
22550
  auth: "admin"
22459
- }), method(object({ deviceId: number() }), object({
22551
+ }), method(object({
22552
+ deviceId: number(),
22553
+ reason: OpsLogReasonSchema.optional()
22554
+ }), object({
22460
22555
  floorMs: number().nullable(),
22461
22556
  deletedBuckets: number().int(),
22462
22557
  reclaimedBytes: number().int()
22463
22558
  }), {
22464
22559
  kind: "mutation",
22465
22560
  auth: "admin"
22561
+ }), method(object({
22562
+ deviceId: number(),
22563
+ fromMs: number().optional(),
22564
+ toMs: number().optional()
22565
+ }), object({
22566
+ deletedBuckets: number().int(),
22567
+ reclaimedBytes: number().int()
22568
+ }), {
22569
+ kind: "mutation",
22570
+ auth: "admin"
22571
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
22572
+ kind: "query",
22573
+ auth: "admin"
22466
22574
  });
22467
22575
  /**
22468
22576
  * `recordingExport` cap — render a footage time range into a single downloadable
@@ -25584,6 +25692,12 @@ Object.freeze({
25584
25692
  addonId: null,
25585
25693
  access: "delete"
25586
25694
  },
25695
+ "pipelineAnalytics.deleteDeviceEvents": {
25696
+ capName: "pipeline-analytics",
25697
+ capScope: "device",
25698
+ addonId: null,
25699
+ access: "delete"
25700
+ },
25587
25701
  "pipelineAnalytics.deleteTracks": {
25588
25702
  capName: "pipeline-analytics",
25589
25703
  capScope: "device",
@@ -25614,6 +25728,12 @@ Object.freeze({
25614
25728
  addonId: null,
25615
25729
  access: "view"
25616
25730
  },
25731
+ "pipelineAnalytics.getEventStoreFootprint": {
25732
+ capName: "pipeline-analytics",
25733
+ capScope: "device",
25734
+ addonId: null,
25735
+ access: "view"
25736
+ },
25617
25737
  "pipelineAnalytics.getKeyEvents": {
25618
25738
  capName: "pipeline-analytics",
25619
25739
  capScope: "device",
@@ -25656,6 +25776,12 @@ Object.freeze({
25656
25776
  addonId: null,
25657
25777
  access: "view"
25658
25778
  },
25779
+ "pipelineAnalytics.listOpsLog": {
25780
+ capName: "pipeline-analytics",
25781
+ capScope: "device",
25782
+ addonId: null,
25783
+ access: "view"
25784
+ },
25659
25785
  "pipelineAnalytics.listRecentTracks": {
25660
25786
  capName: "pipeline-analytics",
25661
25787
  capScope: "device",
@@ -25668,6 +25794,12 @@ Object.freeze({
25668
25794
  addonId: null,
25669
25795
  access: "view"
25670
25796
  },
25797
+ "pipelineAnalytics.pruneEvents": {
25798
+ capName: "pipeline-analytics",
25799
+ capScope: "device",
25800
+ addonId: null,
25801
+ access: "create"
25802
+ },
25671
25803
  "pipelineAnalytics.pruneEventsBefore": {
25672
25804
  capName: "pipeline-analytics",
25673
25805
  capScope: "device",
@@ -26430,6 +26562,12 @@ Object.freeze({
26430
26562
  addonId: null,
26431
26563
  access: "create"
26432
26564
  },
26565
+ "recording.deleteFootprint": {
26566
+ capName: "recording",
26567
+ capScope: "system",
26568
+ addonId: null,
26569
+ access: "delete"
26570
+ },
26433
26571
  "recording.getAvailability": {
26434
26572
  capName: "recording",
26435
26573
  capScope: "system",
@@ -26460,6 +26598,12 @@ Object.freeze({
26460
26598
  addonId: null,
26461
26599
  access: "view"
26462
26600
  },
26601
+ "recording.listOpsLog": {
26602
+ capName: "recording",
26603
+ capScope: "system",
26604
+ addonId: null,
26605
+ access: "view"
26606
+ },
26463
26607
  "recording.locateSegment": {
26464
26608
  capName: "recording",
26465
26609
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",