@camstack/addon-provider-velux 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
@@ -7358,6 +7358,62 @@ var RecordingConfigSchema = object({
7358
7358
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7359
7359
  });
7360
7360
  /**
7361
+ * Ops-log — the durable, append-only operations audit shared by the
7362
+ * recordings and events management surfaces.
7363
+ *
7364
+ * ONE row shape is reused for both domains so a single "Activity" view can
7365
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7366
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7367
+ * management operation, WHY it ran (reason), and its measurable effect
7368
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7369
+ * never fail the operation it records.
7370
+ */
7371
+ /** Which management domain the operation belongs to. */
7372
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7373
+ /** The kind of management operation performed. */
7374
+ var OpsLogOpSchema = _enum([
7375
+ "prune",
7376
+ "manual-delete",
7377
+ "rescan",
7378
+ "retention-run"
7379
+ ]);
7380
+ /** Why the operation ran. */
7381
+ var OpsLogReasonSchema = _enum([
7382
+ "retention",
7383
+ "quota",
7384
+ "manual",
7385
+ "operator"
7386
+ ]);
7387
+ /** One audit row, shared verbatim by both domains. */
7388
+ var OpsLogEntrySchema = object({
7389
+ /** Unique row id. */
7390
+ id: string(),
7391
+ /** Epoch ms the operation completed. */
7392
+ at: number(),
7393
+ domain: OpsLogDomainSchema,
7394
+ op: OpsLogOpSchema,
7395
+ reason: OpsLogReasonSchema,
7396
+ /** The camera the op targeted; null for a cluster/global op. */
7397
+ deviceId: number().nullable(),
7398
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7399
+ nodeId: string(),
7400
+ /** Buckets / rows deleted (op-specific unit). */
7401
+ itemsAffected: number(),
7402
+ /** Bytes reclaimed by the op (0 when not measurable). */
7403
+ bytesReclaimed: number(),
7404
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7405
+ detail: string().nullable(),
7406
+ /** Who/what triggered the op. */
7407
+ actor: string()
7408
+ });
7409
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7410
+ var OpsLogQueryInputSchema = object({
7411
+ /** Restrict to a single camera; omit for every row. */
7412
+ deviceId: number().optional(),
7413
+ /** Max rows returned, newest-first. */
7414
+ limit: number().int().min(1).max(1e3).optional()
7415
+ });
7416
+ /**
7361
7417
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7362
7418
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7363
7419
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -14821,9 +14877,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
14821
14877
  * `package` backs the package-drop detector — a package zone is a
14822
14878
  * `ZoneRule` on the `'package'` stage referencing drawn polygons
14823
14879
  * (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
14824
- * The orchestrator provider that writes this stage lands in a later
14825
- * slice; until then the mirror carries only `{motion, detection}` and
14826
- * consumers read `package` as absent (treat as `[]`).
14880
+ * The orchestrator provider writes this stage as a first-class slice
14881
+ * (Phase 4): every mutation mirrors the full `{motion, detection,
14882
+ * package}` shape, so consumers read the current package rules directly
14883
+ * off `device.state.zoneRules.value.package`.
14827
14884
  */
14828
14885
  runtimeState: object({
14829
14886
  motion: array(ZoneRuleSchema).readonly(),
@@ -19140,6 +19197,26 @@ var TrackCascadeCountsSchema = object({
19140
19197
  /** Per-track CLIP search vectors removed (best-effort). */
19141
19198
  embeddings: number().int()
19142
19199
  });
19200
+ /** Event-store footprint for one camera. */
19201
+ var EventStoreDeviceFootprintSchema = object({
19202
+ deviceId: number(),
19203
+ /** Persisted event rows (motion + object + audio) for the camera. */
19204
+ rows: number().int(),
19205
+ /** Event-owned media bytes on disk for the camera. */
19206
+ bytes: number().int()
19207
+ });
19208
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
19209
+ var EventStoreFootprintSchema = object({
19210
+ totalRows: number().int(),
19211
+ totalBytes: number().int(),
19212
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
19213
+ });
19214
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
19215
+ var EventPruneCountsSchema = object({
19216
+ motion: number().int(),
19217
+ object: number().int(),
19218
+ audio: number().int()
19219
+ });
19143
19220
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
19144
19221
  deviceId: number(),
19145
19222
  trackId: string()
@@ -19203,6 +19280,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19203
19280
  }), {
19204
19281
  kind: "mutation",
19205
19282
  auth: "admin"
19283
+ }), method(object({}), EventStoreFootprintSchema, {
19284
+ kind: "query",
19285
+ auth: "admin"
19286
+ }), method(object({
19287
+ olderThanMs: number(),
19288
+ reason: OpsLogReasonSchema.optional()
19289
+ }), EventPruneCountsSchema, {
19290
+ kind: "mutation",
19291
+ auth: "admin"
19292
+ }), method(object({ deviceId: number() }), EventPruneCountsSchema, {
19293
+ kind: "mutation",
19294
+ auth: "admin"
19295
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19296
+ kind: "query",
19297
+ auth: "admin"
19206
19298
  }), method(object({
19207
19299
  eventId: string(),
19208
19300
  kind: MediaFileKindEnum.optional()
@@ -22436,13 +22528,29 @@ method(object({
22436
22528
  }), method(object({ deviceId: number() }), RecordingStatusSchema, {
22437
22529
  kind: "mutation",
22438
22530
  auth: "admin"
22439
- }), method(object({ deviceId: number() }), object({
22531
+ }), method(object({
22532
+ deviceId: number(),
22533
+ reason: OpsLogReasonSchema.optional()
22534
+ }), object({
22440
22535
  floorMs: number().nullable(),
22441
22536
  deletedBuckets: number().int(),
22442
22537
  reclaimedBytes: number().int()
22443
22538
  }), {
22444
22539
  kind: "mutation",
22445
22540
  auth: "admin"
22541
+ }), method(object({
22542
+ deviceId: number(),
22543
+ fromMs: number().optional(),
22544
+ toMs: number().optional()
22545
+ }), object({
22546
+ deletedBuckets: number().int(),
22547
+ reclaimedBytes: number().int()
22548
+ }), {
22549
+ kind: "mutation",
22550
+ auth: "admin"
22551
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
22552
+ kind: "query",
22553
+ auth: "admin"
22446
22554
  });
22447
22555
  /**
22448
22556
  * `recordingExport` cap — render a footage time range into a single downloadable
@@ -25564,6 +25672,12 @@ Object.freeze({
25564
25672
  addonId: null,
25565
25673
  access: "delete"
25566
25674
  },
25675
+ "pipelineAnalytics.deleteDeviceEvents": {
25676
+ capName: "pipeline-analytics",
25677
+ capScope: "device",
25678
+ addonId: null,
25679
+ access: "delete"
25680
+ },
25567
25681
  "pipelineAnalytics.deleteTracks": {
25568
25682
  capName: "pipeline-analytics",
25569
25683
  capScope: "device",
@@ -25594,6 +25708,12 @@ Object.freeze({
25594
25708
  addonId: null,
25595
25709
  access: "view"
25596
25710
  },
25711
+ "pipelineAnalytics.getEventStoreFootprint": {
25712
+ capName: "pipeline-analytics",
25713
+ capScope: "device",
25714
+ addonId: null,
25715
+ access: "view"
25716
+ },
25597
25717
  "pipelineAnalytics.getKeyEvents": {
25598
25718
  capName: "pipeline-analytics",
25599
25719
  capScope: "device",
@@ -25636,6 +25756,12 @@ Object.freeze({
25636
25756
  addonId: null,
25637
25757
  access: "view"
25638
25758
  },
25759
+ "pipelineAnalytics.listOpsLog": {
25760
+ capName: "pipeline-analytics",
25761
+ capScope: "device",
25762
+ addonId: null,
25763
+ access: "view"
25764
+ },
25639
25765
  "pipelineAnalytics.listRecentTracks": {
25640
25766
  capName: "pipeline-analytics",
25641
25767
  capScope: "device",
@@ -25648,6 +25774,12 @@ Object.freeze({
25648
25774
  addonId: null,
25649
25775
  access: "view"
25650
25776
  },
25777
+ "pipelineAnalytics.pruneEvents": {
25778
+ capName: "pipeline-analytics",
25779
+ capScope: "device",
25780
+ addonId: null,
25781
+ access: "create"
25782
+ },
25651
25783
  "pipelineAnalytics.pruneEventsBefore": {
25652
25784
  capName: "pipeline-analytics",
25653
25785
  capScope: "device",
@@ -26410,6 +26542,12 @@ Object.freeze({
26410
26542
  addonId: null,
26411
26543
  access: "create"
26412
26544
  },
26545
+ "recording.deleteFootprint": {
26546
+ capName: "recording",
26547
+ capScope: "system",
26548
+ addonId: null,
26549
+ access: "delete"
26550
+ },
26413
26551
  "recording.getAvailability": {
26414
26552
  capName: "recording",
26415
26553
  capScope: "system",
@@ -26440,6 +26578,12 @@ Object.freeze({
26440
26578
  addonId: null,
26441
26579
  access: "view"
26442
26580
  },
26581
+ "recording.listOpsLog": {
26582
+ capName: "recording",
26583
+ capScope: "system",
26584
+ addonId: null,
26585
+ access: "view"
26586
+ },
26443
26587
  "recording.locateSegment": {
26444
26588
  capName: "recording",
26445
26589
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -7357,6 +7357,62 @@ var RecordingConfigSchema = object({
7357
7357
  scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7358
7358
  });
7359
7359
  /**
7360
+ * Ops-log — the durable, append-only operations audit shared by the
7361
+ * recordings and events management surfaces.
7362
+ *
7363
+ * ONE row shape is reused for both domains so a single "Activity" view can
7364
+ * merge the recorder's DurableState ring (recordings ops-log) and the
7365
+ * pipeline-analytics SQLite collection (events ops-log). Each row records a
7366
+ * management operation, WHY it ran (reason), and its measurable effect
7367
+ * (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
7368
+ * never fail the operation it records.
7369
+ */
7370
+ /** Which management domain the operation belongs to. */
7371
+ var OpsLogDomainSchema = _enum(["recording", "events"]);
7372
+ /** The kind of management operation performed. */
7373
+ var OpsLogOpSchema = _enum([
7374
+ "prune",
7375
+ "manual-delete",
7376
+ "rescan",
7377
+ "retention-run"
7378
+ ]);
7379
+ /** Why the operation ran. */
7380
+ var OpsLogReasonSchema = _enum([
7381
+ "retention",
7382
+ "quota",
7383
+ "manual",
7384
+ "operator"
7385
+ ]);
7386
+ /** One audit row, shared verbatim by both domains. */
7387
+ var OpsLogEntrySchema = object({
7388
+ /** Unique row id. */
7389
+ id: string(),
7390
+ /** Epoch ms the operation completed. */
7391
+ at: number(),
7392
+ domain: OpsLogDomainSchema,
7393
+ op: OpsLogOpSchema,
7394
+ reason: OpsLogReasonSchema,
7395
+ /** The camera the op targeted; null for a cluster/global op. */
7396
+ deviceId: number().nullable(),
7397
+ /** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
7398
+ nodeId: string(),
7399
+ /** Buckets / rows deleted (op-specific unit). */
7400
+ itemsAffected: number(),
7401
+ /** Bytes reclaimed by the op (0 when not measurable). */
7402
+ bytesReclaimed: number(),
7403
+ /** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
7404
+ detail: string().nullable(),
7405
+ /** Who/what triggered the op. */
7406
+ actor: string()
7407
+ });
7408
+ /** Shared query input for the per-domain `listOpsLog` cap methods. */
7409
+ var OpsLogQueryInputSchema = object({
7410
+ /** Restrict to a single camera; omit for every row. */
7411
+ deviceId: number().optional(),
7412
+ /** Max rows returned, newest-first. */
7413
+ limit: number().int().min(1).max(1e3).optional()
7414
+ });
7415
+ /**
7360
7416
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
7361
7417
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
7362
7418
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -14820,9 +14876,10 @@ var DEVICE_LOCAL_STATE_CAPS = {
14820
14876
  * `package` backs the package-drop detector — a package zone is a
14821
14877
  * `ZoneRule` on the `'package'` stage referencing drawn polygons
14822
14878
  * (see docs/superpowers/specs/2026-07-17-package-zones-design.md §3.1).
14823
- * The orchestrator provider that writes this stage lands in a later
14824
- * slice; until then the mirror carries only `{motion, detection}` and
14825
- * consumers read `package` as absent (treat as `[]`).
14879
+ * The orchestrator provider writes this stage as a first-class slice
14880
+ * (Phase 4): every mutation mirrors the full `{motion, detection,
14881
+ * package}` shape, so consumers read the current package rules directly
14882
+ * off `device.state.zoneRules.value.package`.
14826
14883
  */
14827
14884
  runtimeState: object({
14828
14885
  motion: array(ZoneRuleSchema).readonly(),
@@ -19139,6 +19196,26 @@ var TrackCascadeCountsSchema = object({
19139
19196
  /** Per-track CLIP search vectors removed (best-effort). */
19140
19197
  embeddings: number().int()
19141
19198
  });
19199
+ /** Event-store footprint for one camera. */
19200
+ var EventStoreDeviceFootprintSchema = object({
19201
+ deviceId: number(),
19202
+ /** Persisted event rows (motion + object + audio) for the camera. */
19203
+ rows: number().int(),
19204
+ /** Event-owned media bytes on disk for the camera. */
19205
+ bytes: number().int()
19206
+ });
19207
+ /** Aggregate event-store footprint: global totals + per-camera breakdown. */
19208
+ var EventStoreFootprintSchema = object({
19209
+ totalRows: number().int(),
19210
+ totalBytes: number().int(),
19211
+ devices: array(EventStoreDeviceFootprintSchema).readonly()
19212
+ });
19213
+ /** Per-kind counts returned by the event-prune / device-delete mutations. */
19214
+ var EventPruneCountsSchema = object({
19215
+ motion: number().int(),
19216
+ object: number().int(),
19217
+ audio: number().int()
19218
+ });
19142
19219
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
19143
19220
  deviceId: number(),
19144
19221
  trackId: string()
@@ -19202,6 +19279,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19202
19279
  }), {
19203
19280
  kind: "mutation",
19204
19281
  auth: "admin"
19282
+ }), method(object({}), EventStoreFootprintSchema, {
19283
+ kind: "query",
19284
+ auth: "admin"
19285
+ }), method(object({
19286
+ olderThanMs: number(),
19287
+ reason: OpsLogReasonSchema.optional()
19288
+ }), EventPruneCountsSchema, {
19289
+ kind: "mutation",
19290
+ auth: "admin"
19291
+ }), method(object({ deviceId: number() }), EventPruneCountsSchema, {
19292
+ kind: "mutation",
19293
+ auth: "admin"
19294
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19295
+ kind: "query",
19296
+ auth: "admin"
19205
19297
  }), method(object({
19206
19298
  eventId: string(),
19207
19299
  kind: MediaFileKindEnum.optional()
@@ -22435,13 +22527,29 @@ method(object({
22435
22527
  }), method(object({ deviceId: number() }), RecordingStatusSchema, {
22436
22528
  kind: "mutation",
22437
22529
  auth: "admin"
22438
- }), method(object({ deviceId: number() }), object({
22530
+ }), method(object({
22531
+ deviceId: number(),
22532
+ reason: OpsLogReasonSchema.optional()
22533
+ }), object({
22439
22534
  floorMs: number().nullable(),
22440
22535
  deletedBuckets: number().int(),
22441
22536
  reclaimedBytes: number().int()
22442
22537
  }), {
22443
22538
  kind: "mutation",
22444
22539
  auth: "admin"
22540
+ }), method(object({
22541
+ deviceId: number(),
22542
+ fromMs: number().optional(),
22543
+ toMs: number().optional()
22544
+ }), object({
22545
+ deletedBuckets: number().int(),
22546
+ reclaimedBytes: number().int()
22547
+ }), {
22548
+ kind: "mutation",
22549
+ auth: "admin"
22550
+ }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
22551
+ kind: "query",
22552
+ auth: "admin"
22445
22553
  });
22446
22554
  /**
22447
22555
  * `recordingExport` cap — render a footage time range into a single downloadable
@@ -25563,6 +25671,12 @@ Object.freeze({
25563
25671
  addonId: null,
25564
25672
  access: "delete"
25565
25673
  },
25674
+ "pipelineAnalytics.deleteDeviceEvents": {
25675
+ capName: "pipeline-analytics",
25676
+ capScope: "device",
25677
+ addonId: null,
25678
+ access: "delete"
25679
+ },
25566
25680
  "pipelineAnalytics.deleteTracks": {
25567
25681
  capName: "pipeline-analytics",
25568
25682
  capScope: "device",
@@ -25593,6 +25707,12 @@ Object.freeze({
25593
25707
  addonId: null,
25594
25708
  access: "view"
25595
25709
  },
25710
+ "pipelineAnalytics.getEventStoreFootprint": {
25711
+ capName: "pipeline-analytics",
25712
+ capScope: "device",
25713
+ addonId: null,
25714
+ access: "view"
25715
+ },
25596
25716
  "pipelineAnalytics.getKeyEvents": {
25597
25717
  capName: "pipeline-analytics",
25598
25718
  capScope: "device",
@@ -25635,6 +25755,12 @@ Object.freeze({
25635
25755
  addonId: null,
25636
25756
  access: "view"
25637
25757
  },
25758
+ "pipelineAnalytics.listOpsLog": {
25759
+ capName: "pipeline-analytics",
25760
+ capScope: "device",
25761
+ addonId: null,
25762
+ access: "view"
25763
+ },
25638
25764
  "pipelineAnalytics.listRecentTracks": {
25639
25765
  capName: "pipeline-analytics",
25640
25766
  capScope: "device",
@@ -25647,6 +25773,12 @@ Object.freeze({
25647
25773
  addonId: null,
25648
25774
  access: "view"
25649
25775
  },
25776
+ "pipelineAnalytics.pruneEvents": {
25777
+ capName: "pipeline-analytics",
25778
+ capScope: "device",
25779
+ addonId: null,
25780
+ access: "create"
25781
+ },
25650
25782
  "pipelineAnalytics.pruneEventsBefore": {
25651
25783
  capName: "pipeline-analytics",
25652
25784
  capScope: "device",
@@ -26409,6 +26541,12 @@ Object.freeze({
26409
26541
  addonId: null,
26410
26542
  access: "create"
26411
26543
  },
26544
+ "recording.deleteFootprint": {
26545
+ capName: "recording",
26546
+ capScope: "system",
26547
+ addonId: null,
26548
+ access: "delete"
26549
+ },
26412
26550
  "recording.getAvailability": {
26413
26551
  capName: "recording",
26414
26552
  capScope: "system",
@@ -26439,6 +26577,12 @@ Object.freeze({
26439
26577
  addonId: null,
26440
26578
  access: "view"
26441
26579
  },
26580
+ "recording.listOpsLog": {
26581
+ capName: "recording",
26582
+ capScope: "system",
26583
+ addonId: null,
26584
+ access: "view"
26585
+ },
26442
26586
  "recording.locateSegment": {
26443
26587
  capName: "recording",
26444
26588
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-velux",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",