@camstack/system 1.2.27 → 1.2.29

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 (58) hide show
  1. package/dist/addon-runner.js +3 -3
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.d.ts +0 -7
  8. package/dist/builtins/alerts/alerts.addon.js +47 -25
  9. package/dist/builtins/alerts/alerts.addon.mjs +47 -25
  10. package/dist/builtins/alerts/prune-policy.d.ts +44 -0
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  13. package/dist/builtins/console-logging/index.js +1 -1
  14. package/dist/builtins/console-logging/index.mjs +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  16. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  19. package/dist/builtins/hub-forwarder/index.js +1 -1
  20. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  23. package/dist/builtins/local-network/local-network.addon.js +1 -1
  24. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  25. package/dist/builtins/loki-logging/index.js +1 -1
  26. package/dist/builtins/loki-logging/index.mjs +1 -1
  27. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  29. package/dist/builtins/platform-probe/index.js +1 -1
  30. package/dist/builtins/platform-probe/index.mjs +1 -1
  31. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  33. package/dist/builtins/snapshot/index.js +1 -1
  34. package/dist/builtins/snapshot/index.mjs +1 -1
  35. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +7 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -2
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +22 -4
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +22 -4
  41. package/dist/builtins/storage-orchestrator/data-store-dispatch.d.ts +12 -0
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +18 -7
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +78 -11
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +78 -11
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-BXmFvn3h.mjs → dist-B7hOpr5i.mjs} +411 -166
  50. package/dist/{dist-BxtIzexq.js → dist-CPmFYLqq.js} +416 -165
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +106 -2
  53. package/dist/index.mjs +102 -3
  54. package/dist/kernel/heap-watch.d.ts +36 -0
  55. package/dist/kernel/transport/uds-event-bus.d.ts +4 -1
  56. package/dist/{manifest-python-deps-KZ00cbfP.js → manifest-python-deps-BqE5j0-O.js} +25 -4
  57. package/dist/{manifest-python-deps-BNOApgK0.mjs → manifest-python-deps-Ck4-9K9m.mjs} +25 -4
  58. package/package.json +7 -3
@@ -3381,14 +3381,7 @@ var RecordingConfigSchema = z.object({
3381
3381
  * windows only — existing sheets are immutable, and each window's index
3382
3382
  * carries its own tile dims so mixed-preset history renders correctly.
3383
3383
  */
3384
- scrubThumbnails: ScrubThumbnailPresetSchema.optional(),
3385
- /**
3386
- * OPT-IN thumbnail-strip generation for this camera: every keyframe of the
3387
- * low recording saved as a JPEG (the fast-drag scrub depth), a derived
3388
- * cache that eviction reclaims with the footage. Absent/false = no strips
3389
- * are written and scrub reads exact keyframes at every velocity.
3390
- */
3391
- stripsEnabled: z.boolean().optional()
3384
+ scrubThumbnails: ScrubThumbnailPresetSchema.optional()
3392
3385
  }).strict();
3393
3386
  /**
3394
3387
  * Ops-log — the durable, append-only operations audit shared by the
@@ -3450,7 +3443,7 @@ var OpsLogQueryInputSchema = z.object({
3450
3443
  /**
3451
3444
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
3452
3445
  *
3453
- * One shape shared by the recorder's `relocateFootage` (segments + strips) and
3446
+ * One shape shared by the recorder's `relocateFootage` (segments) and
3454
3447
  * pipeline-analytics' `relocateMedia` (event media blobs) so the admin Data
3455
3448
  * page renders both movers with one component. Jobs are in-RAM (a restart
3456
3449
  * forgets them — re-running is safe by construction: copy-if-absent, delete
@@ -3472,7 +3465,7 @@ var RelocateJobSchema = z.object({
3472
3465
  toLocationId: z.string(),
3473
3466
  /** Scoped device, or null = every device. */
3474
3467
  deviceId: z.number().nullable(),
3475
- /** What the job moves (owner-addon specific: segments/strips or media). */
3468
+ /** What the job moves (owner-addon specific: segments or media). */
3476
3469
  entities: z.array(z.string()),
3477
3470
  filesMoved: z.number().int(),
3478
3471
  bytesMoved: z.number().int(),
@@ -3486,7 +3479,7 @@ var RelocateFootageInputSchema = z.object({
3486
3479
  deviceId: z.number().optional(),
3487
3480
  fromLocationId: z.string(),
3488
3481
  toLocationId: z.string(),
3489
- entities: z.array(z.enum(["segments", "strips"])).optional(),
3482
+ entities: z.array(z.enum(["segments"])).optional(),
3490
3483
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
3491
3484
  * never allowed to starve live writers. */
3492
3485
  throttleMbps: z.number().min(1).max(1e3).optional()
@@ -14538,6 +14531,292 @@ var decoderCapability = {
14538
14531
  }
14539
14532
  };
14540
14533
  /**
14534
+ * Query filter for settings-store collections.
14535
+ */
14536
+ var QueryFilterSchema = z.object({
14537
+ where: z.record(z.string(), z.unknown()).optional(),
14538
+ whereIn: z.record(z.string(), z.array(z.unknown())).optional(),
14539
+ whereBetween: z.record(z.string(), z.tuple([z.unknown(), z.unknown()])).optional(),
14540
+ orderBy: z.object({
14541
+ field: z.string(),
14542
+ direction: z.enum(["asc", "desc"])
14543
+ }).optional(),
14544
+ limit: z.number().optional(),
14545
+ offset: z.number().optional()
14546
+ });
14547
+ /** A single stored record: `{ id, data }`. */
14548
+ var SettingsRecordSchema = z.object({
14549
+ id: z.string(),
14550
+ data: z.record(z.string(), z.unknown())
14551
+ });
14552
+ /**
14553
+ * Column declaration for a structured (SQL-backed) collection.
14554
+ *
14555
+ * Logical types — the backend translates each to the matching SQLite
14556
+ * storage class and handles per-type marshaling:
14557
+ * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
14558
+ * - `JSON` — TEXT under the hood; serialised on write, parsed on read
14559
+ * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
14560
+ */
14561
+ var CollectionColumnSchema = z.object({
14562
+ name: z.string(),
14563
+ type: z.enum([
14564
+ "TEXT",
14565
+ "INTEGER",
14566
+ "REAL",
14567
+ "JSON",
14568
+ "BOOLEAN"
14569
+ ]),
14570
+ primaryKey: z.boolean().optional(),
14571
+ notNull: z.boolean().optional(),
14572
+ unique: z.boolean().optional()
14573
+ });
14574
+ var CollectionIndexSchema = z.object({
14575
+ name: z.string(),
14576
+ columns: z.array(z.string()).readonly(),
14577
+ unique: z.boolean().optional()
14578
+ });
14579
+ /**
14580
+ * settings-store — singleton capability for addon-scoped persistence.
14581
+ *
14582
+ * Every method operates within a `collection`. An optional `namespace`
14583
+ * field provides access to additional data spaces beyond the default
14584
+ * addon settings — useful for business data (events, tracks, faces, etc.).
14585
+ *
14586
+ * **Scoping is the CALLER's, and it is opt-in.** The table is
14587
+ * `namespace ? `${namespace}:${collection}` : collection` — nothing
14588
+ * consults the identity of the caller. An earlier version of this comment
14589
+ * claimed the implementation prefixes every collection with the calling
14590
+ * addon's ID and that "addons never see each other's data"; that was never
14591
+ * true, and this same file contradicted it under `declareCollection`. What
14592
+ * exists is `addon-context-factory`, which passes `namespace: addonId` ON
14593
+ * THE ADDON'S BEHALF for the `addon-settings` / `addon-devices` paths only.
14594
+ * Business collections use bare names, and any caller may name any
14595
+ * namespace, or none. Making the door enforce it is tracked separately —
14596
+ * it renames tables, so it needs a migration.
14597
+ *
14598
+ * - `{ collection: 'addon-settings' }` → table `addon-settings`
14599
+ * - `{ namespace: 'my-addon', collection: 'addon-settings' }` →
14600
+ * table `my-addon:addon-settings`
14601
+ *
14602
+ * Served by the **storage-orchestrator** builtin, which dispatches to the
14603
+ * `data-store-provider` engine registered for the collection
14604
+ * (`sqlite-settings`, a SQLite WAL backend, today). One addon owns the
14605
+ * data door; engines sit behind it
14606
+ * ([D44](../../../../docs/decisions/adr-0044.md)).
14607
+ * Addons access it via `ctx.api.settingsStore.*`.
14608
+ */
14609
+ var settingsStoreCapability = {
14610
+ name: "settings-store",
14611
+ scope: "system",
14612
+ mode: "singleton",
14613
+ methods: {
14614
+ /** Get a single value by key from a collection. */
14615
+ get: method(z.object({
14616
+ namespace: z.string().optional(),
14617
+ collection: z.string(),
14618
+ key: z.string()
14619
+ }), z.unknown()),
14620
+ /** Set a value by key in a collection (upsert). */
14621
+ set: method(z.object({
14622
+ namespace: z.string().optional(),
14623
+ collection: z.string(),
14624
+ key: z.string(),
14625
+ value: z.unknown()
14626
+ }), z.void(), { kind: "mutation" }),
14627
+ /** Get all entries matching an optional filter. */
14628
+ query: method(z.object({
14629
+ namespace: z.string().optional(),
14630
+ collection: z.string(),
14631
+ filter: QueryFilterSchema.optional()
14632
+ }), z.array(SettingsRecordSchema).readonly()),
14633
+ /** Insert a new record. */
14634
+ insert: method(z.object({
14635
+ namespace: z.string().optional(),
14636
+ collection: z.string(),
14637
+ record: SettingsRecordSchema
14638
+ }), z.void(), { kind: "mutation" }),
14639
+ /** Update an existing record by ID. */
14640
+ update: method(z.object({
14641
+ namespace: z.string().optional(),
14642
+ collection: z.string(),
14643
+ id: z.string(),
14644
+ data: z.record(z.string(), z.unknown())
14645
+ }), z.void(), { kind: "mutation" }),
14646
+ /** Delete a record by key/ID. */
14647
+ delete: method(z.object({
14648
+ namespace: z.string().optional(),
14649
+ collection: z.string(),
14650
+ key: z.string()
14651
+ }), z.void(), { kind: "mutation" }),
14652
+ /** Count entries in a collection, optionally filtered. */
14653
+ count: method(z.object({
14654
+ namespace: z.string().optional(),
14655
+ collection: z.string(),
14656
+ filter: QueryFilterSchema.optional()
14657
+ }), z.number()),
14658
+ /** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
14659
+ histogram: method(z.object({
14660
+ namespace: z.string().optional(),
14661
+ collection: z.string(),
14662
+ field: z.string(),
14663
+ bucketSize: z.number().int().positive(),
14664
+ origin: z.number().int(),
14665
+ filter: QueryFilterSchema.optional()
14666
+ }), z.array(z.object({
14667
+ bucket: z.number().int(),
14668
+ count: z.number().int()
14669
+ })).readonly()),
14670
+ /** Check if a collection is empty. */
14671
+ isEmpty: method(z.object({
14672
+ namespace: z.string().optional(),
14673
+ collection: z.string()
14674
+ }), z.boolean()),
14675
+ /**
14676
+ * Declare a typed (SQL-backed) collection with explicit columns +
14677
+ * indexes. Idempotent: re-declaring an existing collection with the
14678
+ * same shape is a no-op; shape changes (new columns, new indexes)
14679
+ * are applied additively. Subsequent `insert` / `update` / `delete`
14680
+ * / `query` calls on this collection use typed columns instead of
14681
+ * JSON-blob storage — `record.data` fields are spread across
14682
+ * columns, `query.filter.where` matches real columns (no
14683
+ * `json_extract` overhead), `orderBy` uses column indexes.
14684
+ *
14685
+ * Addons call this in `onInitialize` before their first read/write.
14686
+ * Collection names should be namespaced by addon (e.g.
14687
+ * `pipeline-analytics:object-events`) to avoid cross-addon
14688
+ * clashes — no automatic prefix is added.
14689
+ */
14690
+ declareCollection: method(z.object({
14691
+ namespace: z.string().optional(),
14692
+ collection: z.string(),
14693
+ columns: z.array(CollectionColumnSchema).readonly(),
14694
+ indexes: z.array(CollectionIndexSchema).readonly().optional()
14695
+ }), z.void(), { kind: "mutation" })
14696
+ }
14697
+ };
14698
+ /**
14699
+ * What one engine says about itself. The orchestrator uses `kind` to pick
14700
+ * a registrant for a collection; `engineId` is what a log line names when
14701
+ * a call is routed or refused.
14702
+ */
14703
+ var EngineInfoSchema = z.object({
14704
+ engineId: z.string(),
14705
+ /**
14706
+ * `relational` — rows, columns, indexes, the surface `settings-store`
14707
+ * has always described. `vector` — an embedding store answering
14708
+ * similarity queries. A registrant declares exactly one; an engine that
14709
+ * does both registers twice, because "both" would make the routing
14710
+ * decision ambiguous at exactly the point it must not be.
14711
+ */
14712
+ kind: z.enum(["relational", "vector"]),
14713
+ displayName: z.string()
14714
+ });
14715
+ /**
14716
+ * data-store-provider — the engine contract behind the data door.
14717
+ *
14718
+ * The sibling of `storage-provider`, for rows instead of bytes. The
14719
+ * orchestrator (singleton `settings-store` cap, owned by the
14720
+ * storage-orchestrator builtin) dispatches every call to the registrant
14721
+ * that serves the collection.
14722
+ *
14723
+ * `internal: true` — consumed only by the orchestrator. Public consumers
14724
+ * go through `settings-store`; they never see this cap, and an engine
14725
+ * never sees a caller.
14726
+ *
14727
+ * Design notes:
14728
+ * - **Stateless dispatch.** Every method carries its own
14729
+ * `namespace` + `collection`, so an engine keeps no per-caller state
14730
+ * and the orchestrator forwards the payload verbatim. Scoping is a
14731
+ * property of the input, not of the connection — see the note on
14732
+ * `settings-store` about what that does and does not guarantee.
14733
+ * - **One registrant today** (`sqlite-settings`). The collection shape
14734
+ * exists so a second engine is a registration rather than a second
14735
+ * door ([D44](../../../../docs/decisions/adr-0044.md)).
14736
+ *
14737
+ * The method set is deliberately identical to `settings-store`'s: the
14738
+ * orchestrator is a router, not a translator. A capability the door
14739
+ * gains, an engine must be able to answer.
14740
+ */
14741
+ var dataStoreProviderCapability = {
14742
+ name: "data-store-provider",
14743
+ scope: "system",
14744
+ mode: "collection",
14745
+ internal: true,
14746
+ methods: {
14747
+ /** Self-description — how the orchestrator picks a registrant. */
14748
+ getEngineInfo: method(z.void(), EngineInfoSchema),
14749
+ /** Get a single value by key from a collection. */
14750
+ get: method(z.object({
14751
+ namespace: z.string().optional(),
14752
+ collection: z.string(),
14753
+ key: z.string()
14754
+ }), z.unknown()),
14755
+ /** Set a value by key in a collection (upsert). */
14756
+ set: method(z.object({
14757
+ namespace: z.string().optional(),
14758
+ collection: z.string(),
14759
+ key: z.string(),
14760
+ value: z.unknown()
14761
+ }), z.void(), { kind: "mutation" }),
14762
+ /** Get all entries matching an optional filter. */
14763
+ query: method(z.object({
14764
+ namespace: z.string().optional(),
14765
+ collection: z.string(),
14766
+ filter: QueryFilterSchema.optional()
14767
+ }), z.array(SettingsRecordSchema).readonly()),
14768
+ /** Insert a new record. */
14769
+ insert: method(z.object({
14770
+ namespace: z.string().optional(),
14771
+ collection: z.string(),
14772
+ record: SettingsRecordSchema
14773
+ }), z.void(), { kind: "mutation" }),
14774
+ /** Update an existing record by ID. */
14775
+ update: method(z.object({
14776
+ namespace: z.string().optional(),
14777
+ collection: z.string(),
14778
+ id: z.string(),
14779
+ data: z.record(z.string(), z.unknown())
14780
+ }), z.void(), { kind: "mutation" }),
14781
+ /** Delete a record by key/ID. */
14782
+ delete: method(z.object({
14783
+ namespace: z.string().optional(),
14784
+ collection: z.string(),
14785
+ key: z.string()
14786
+ }), z.void(), { kind: "mutation" }),
14787
+ /** Count entries in a collection, optionally filtered. */
14788
+ count: method(z.object({
14789
+ namespace: z.string().optional(),
14790
+ collection: z.string(),
14791
+ filter: QueryFilterSchema.optional()
14792
+ }), z.number()),
14793
+ /** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
14794
+ histogram: method(z.object({
14795
+ namespace: z.string().optional(),
14796
+ collection: z.string(),
14797
+ field: z.string(),
14798
+ bucketSize: z.number().int().positive(),
14799
+ origin: z.number().int(),
14800
+ filter: QueryFilterSchema.optional()
14801
+ }), z.array(z.object({
14802
+ bucket: z.number().int(),
14803
+ count: z.number().int()
14804
+ })).readonly()),
14805
+ /** Check if a collection is empty. */
14806
+ isEmpty: method(z.object({
14807
+ namespace: z.string().optional(),
14808
+ collection: z.string()
14809
+ }), z.boolean()),
14810
+ /** Declare a typed (SQL-backed) collection with columns + indexes. */
14811
+ declareCollection: method(z.object({
14812
+ namespace: z.string().optional(),
14813
+ collection: z.string(),
14814
+ columns: z.array(CollectionColumnSchema).readonly(),
14815
+ indexes: z.array(CollectionIndexSchema).readonly().optional()
14816
+ }), z.void(), { kind: "mutation" })
14817
+ }
14818
+ };
14819
+ /**
14541
14820
  * detection-pipeline — device-scoped facade over the system
14542
14821
  * `pipeline-executor`.
14543
14822
  *
@@ -18926,6 +19205,52 @@ var ServerUpdateStateSchema = z.enum([
18926
19205
  "pending-restart",
18927
19206
  "awaiting-confirmation"
18928
19207
  ]);
19208
+ /**
19209
+ * Verdict of comparing the node's IMMUTABLE baked seed (the Docker image / the
19210
+ * desktop app bundle) against the release the deployment contract would
19211
+ * deliver today. `applyServerUpdate` swaps the data-root closure and NEVER
19212
+ * touches the image, so `runningVersion` can be perfectly current while the
19213
+ * container is weeks old, from a renamed repository nothing rebuilds — which
19214
+ * is exactly what happened on 2026-08-02 (hub on `camstack-server:intel-1.1.74`
19215
+ * while every existing surface said "up to date"). The seed version is the one
19216
+ * image fingerprint a container can see from inside (no docker socket).
19217
+ *
19218
+ * - `in-sync` — seed equals the current release; the node runs the
19219
+ * contract image.
19220
+ * - `behind-patch` — same release series, older patch: the image predates
19221
+ * the current release. Normal between deliberate image
19222
+ * refreshes, but the starter/entrypoint are still old.
19223
+ * - `behind-series` — the seed's major/minor predates the current release
19224
+ * series. The shape of a pinned tag or a dead image
19225
+ * repository; a `docker pull` may fix nothing.
19226
+ * - `ahead` — seed newer than the best-known release (stale registry
19227
+ * check).
19228
+ * - `unknown` — no seed (dev workspace) or nothing to compare against
19229
+ * yet.
19230
+ */
19231
+ var ImageContractStateSchema = z.enum([
19232
+ "in-sync",
19233
+ "behind-patch",
19234
+ "behind-series",
19235
+ "ahead",
19236
+ "unknown"
19237
+ ]);
19238
+ var ImageContractSchema = z.object({
19239
+ state: ImageContractStateSchema,
19240
+ /** The baked seed closure version — the image/app-bundle fingerprint. */
19241
+ seedVersion: z.string().nullable(),
19242
+ /** Best-known version the deployment contract delivers today. */
19243
+ contractVersion: z.string().nullable(),
19244
+ /**
19245
+ * Where `contractVersion` came from: a real registry check (`registry`), or
19246
+ * the node's own running version (`running` — a node can never run code
19247
+ * newer than the newest release, so `seed < running` proves image staleness
19248
+ * even before any registry check has run).
19249
+ */
19250
+ contractSource: z.enum(["registry", "running"]).nullable(),
19251
+ /** One operator-grade sentence: this node runs image X; the contract says Y. */
19252
+ message: z.string()
19253
+ });
18929
19254
  var ServerRollbackInfoSchema = z.object({
18930
19255
  /** The version that failed (or was manually rolled back). */
18931
19256
  fromVersion: z.string(),
@@ -18962,7 +19287,12 @@ var ServerPackageStatusSchema = z.object({
18962
19287
  * versions are being IGNORED. Surfaced as a warning in the UI.
18963
19288
  */
18964
19289
  stateFileCorrupt: z.boolean(),
18965
- lastCheckedAtMs: z.number().nullable()
19290
+ lastCheckedAtMs: z.number().nullable(),
19291
+ /**
19292
+ * Seed-vs-contract verdict (see {@link ImageContractSchema}). Optional for
19293
+ * version skew: an older provider's payload simply omits it.
19294
+ */
19295
+ imageContract: ImageContractSchema.optional()
18966
19296
  });
18967
19297
  var ServerUpdateCheckResultSchema = z.object({
18968
19298
  packageName: z.string(),
@@ -19017,158 +19347,6 @@ version: z.string().optional() }), ServerUpdateActionResultSchema, {
19017
19347
  mount: { kind: "server-provided" }
19018
19348
  };
19019
19349
  /**
19020
- * Query filter for settings-store collections.
19021
- */
19022
- var QueryFilterSchema = z.object({
19023
- where: z.record(z.string(), z.unknown()).optional(),
19024
- whereIn: z.record(z.string(), z.array(z.unknown())).optional(),
19025
- whereBetween: z.record(z.string(), z.tuple([z.unknown(), z.unknown()])).optional(),
19026
- orderBy: z.object({
19027
- field: z.string(),
19028
- direction: z.enum(["asc", "desc"])
19029
- }).optional(),
19030
- limit: z.number().optional(),
19031
- offset: z.number().optional()
19032
- });
19033
- /** A single stored record: `{ id, data }`. */
19034
- var SettingsRecordSchema = z.object({
19035
- id: z.string(),
19036
- data: z.record(z.string(), z.unknown())
19037
- });
19038
- /**
19039
- * Column declaration for a structured (SQL-backed) collection.
19040
- *
19041
- * Logical types — the backend translates each to the matching SQLite
19042
- * storage class and handles per-type marshaling:
19043
- * - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
19044
- * - `JSON` — TEXT under the hood; serialised on write, parsed on read
19045
- * - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
19046
- */
19047
- var CollectionColumnSchema = z.object({
19048
- name: z.string(),
19049
- type: z.enum([
19050
- "TEXT",
19051
- "INTEGER",
19052
- "REAL",
19053
- "JSON",
19054
- "BOOLEAN"
19055
- ]),
19056
- primaryKey: z.boolean().optional(),
19057
- notNull: z.boolean().optional(),
19058
- unique: z.boolean().optional()
19059
- });
19060
- var CollectionIndexSchema = z.object({
19061
- name: z.string(),
19062
- columns: z.array(z.string()).readonly(),
19063
- unique: z.boolean().optional()
19064
- });
19065
- /**
19066
- * settings-store — singleton capability for addon-scoped persistence.
19067
- *
19068
- * Every method operates within a `collection`. An optional `namespace`
19069
- * field provides access to additional data spaces beyond the default
19070
- * addon settings — useful for business data (events, tracks, faces, etc.).
19071
- *
19072
- * Scoping: the implementation prefixes every collection with the calling
19073
- * addon's ID automatically. Addons never see each other's data.
19074
- *
19075
- * - No namespace (default): `"addon-settings"` → `"<addonId>:addon-settings"`
19076
- * - With namespace: `{ namespace: 'events', collection: 'detections' }` →
19077
- * `"<addonId>:events:detections"`
19078
- *
19079
- * Implemented by `@camstack/system/builtins/sqlite-settings` (SQLite WAL backend).
19080
- * Addons access it via `ctx.api.settingsStore.*`.
19081
- */
19082
- var settingsStoreCapability = {
19083
- name: "settings-store",
19084
- scope: "system",
19085
- mode: "singleton",
19086
- methods: {
19087
- /** Get a single value by key from a collection. */
19088
- get: method(z.object({
19089
- namespace: z.string().optional(),
19090
- collection: z.string(),
19091
- key: z.string()
19092
- }), z.unknown()),
19093
- /** Set a value by key in a collection (upsert). */
19094
- set: method(z.object({
19095
- namespace: z.string().optional(),
19096
- collection: z.string(),
19097
- key: z.string(),
19098
- value: z.unknown()
19099
- }), z.void(), { kind: "mutation" }),
19100
- /** Get all entries matching an optional filter. */
19101
- query: method(z.object({
19102
- namespace: z.string().optional(),
19103
- collection: z.string(),
19104
- filter: QueryFilterSchema.optional()
19105
- }), z.array(SettingsRecordSchema).readonly()),
19106
- /** Insert a new record. */
19107
- insert: method(z.object({
19108
- namespace: z.string().optional(),
19109
- collection: z.string(),
19110
- record: SettingsRecordSchema
19111
- }), z.void(), { kind: "mutation" }),
19112
- /** Update an existing record by ID. */
19113
- update: method(z.object({
19114
- namespace: z.string().optional(),
19115
- collection: z.string(),
19116
- id: z.string(),
19117
- data: z.record(z.string(), z.unknown())
19118
- }), z.void(), { kind: "mutation" }),
19119
- /** Delete a record by key/ID. */
19120
- delete: method(z.object({
19121
- namespace: z.string().optional(),
19122
- collection: z.string(),
19123
- key: z.string()
19124
- }), z.void(), { kind: "mutation" }),
19125
- /** Count entries in a collection, optionally filtered. */
19126
- count: method(z.object({
19127
- namespace: z.string().optional(),
19128
- collection: z.string(),
19129
- filter: QueryFilterSchema.optional()
19130
- }), z.number()),
19131
- /** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
19132
- histogram: method(z.object({
19133
- namespace: z.string().optional(),
19134
- collection: z.string(),
19135
- field: z.string(),
19136
- bucketSize: z.number().int().positive(),
19137
- origin: z.number().int(),
19138
- filter: QueryFilterSchema.optional()
19139
- }), z.array(z.object({
19140
- bucket: z.number().int(),
19141
- count: z.number().int()
19142
- })).readonly()),
19143
- /** Check if a collection is empty. */
19144
- isEmpty: method(z.object({
19145
- namespace: z.string().optional(),
19146
- collection: z.string()
19147
- }), z.boolean()),
19148
- /**
19149
- * Declare a typed (SQL-backed) collection with explicit columns +
19150
- * indexes. Idempotent: re-declaring an existing collection with the
19151
- * same shape is a no-op; shape changes (new columns, new indexes)
19152
- * are applied additively. Subsequent `insert` / `update` / `delete`
19153
- * / `query` calls on this collection use typed columns instead of
19154
- * JSON-blob storage — `record.data` fields are spread across
19155
- * columns, `query.filter.where` matches real columns (no
19156
- * `json_extract` overhead), `orderBy` uses column indexes.
19157
- *
19158
- * Addons call this in `onInitialize` before their first read/write.
19159
- * Collection names should be namespaced by addon (e.g.
19160
- * `pipeline-analytics:object-events`) to avoid cross-addon
19161
- * clashes — no automatic prefix is added.
19162
- */
19163
- declareCollection: method(z.object({
19164
- namespace: z.string().optional(),
19165
- collection: z.string(),
19166
- columns: z.array(CollectionColumnSchema).readonly(),
19167
- indexes: z.array(CollectionIndexSchema).readonly().optional()
19168
- }), z.void(), { kind: "mutation" })
19169
- }
19170
- };
19171
- /**
19172
19350
  * `smtp-provider` — pluggable email delivery surface.
19173
19351
  *
19174
19352
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
@@ -22878,7 +23056,7 @@ var recordingCapability = {
22878
23056
  auth: "admin"
22879
23057
  }),
22880
23058
  /**
22881
- * Move footage (segments and/or strips) from one recordings location to
23059
+ * Move footage (recorded segments) from one recordings location to
22882
23060
  * another — the drain workflow's mover (entity-routing spec Phase 4).
22883
23061
  * Throttled copy → size-verify → delete source → index refresh; resumable
22884
23062
  * by construction (copy-if-absent). Single-flight: one job at a time.
@@ -23761,6 +23939,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
23761
23939
  controlCapability,
23762
23940
  coverCapability,
23763
23941
  customModelRegistryCapability,
23942
+ dataStoreProviderCapability,
23764
23943
  dayNightCapability,
23765
23944
  decoderCapability,
23766
23945
  detectionPipelineCapability,
@@ -24766,6 +24945,72 @@ var METHOD_ACCESS_MAP = Object.freeze({
24766
24945
  addonId: null,
24767
24946
  access: "view"
24768
24947
  },
24948
+ "dataStoreProvider.count": {
24949
+ capName: "data-store-provider",
24950
+ capScope: "system",
24951
+ addonId: null,
24952
+ access: "view"
24953
+ },
24954
+ "dataStoreProvider.declareCollection": {
24955
+ capName: "data-store-provider",
24956
+ capScope: "system",
24957
+ addonId: null,
24958
+ access: "create"
24959
+ },
24960
+ "dataStoreProvider.delete": {
24961
+ capName: "data-store-provider",
24962
+ capScope: "system",
24963
+ addonId: null,
24964
+ access: "delete"
24965
+ },
24966
+ "dataStoreProvider.get": {
24967
+ capName: "data-store-provider",
24968
+ capScope: "system",
24969
+ addonId: null,
24970
+ access: "view"
24971
+ },
24972
+ "dataStoreProvider.getEngineInfo": {
24973
+ capName: "data-store-provider",
24974
+ capScope: "system",
24975
+ addonId: null,
24976
+ access: "view"
24977
+ },
24978
+ "dataStoreProvider.histogram": {
24979
+ capName: "data-store-provider",
24980
+ capScope: "system",
24981
+ addonId: null,
24982
+ access: "view"
24983
+ },
24984
+ "dataStoreProvider.insert": {
24985
+ capName: "data-store-provider",
24986
+ capScope: "system",
24987
+ addonId: null,
24988
+ access: "create"
24989
+ },
24990
+ "dataStoreProvider.isEmpty": {
24991
+ capName: "data-store-provider",
24992
+ capScope: "system",
24993
+ addonId: null,
24994
+ access: "view"
24995
+ },
24996
+ "dataStoreProvider.query": {
24997
+ capName: "data-store-provider",
24998
+ capScope: "system",
24999
+ addonId: null,
25000
+ access: "view"
25001
+ },
25002
+ "dataStoreProvider.set": {
25003
+ capName: "data-store-provider",
25004
+ capScope: "system",
25005
+ addonId: null,
25006
+ access: "create"
25007
+ },
25008
+ "dataStoreProvider.update": {
25009
+ capName: "data-store-provider",
25010
+ capScope: "system",
25011
+ addonId: null,
25012
+ access: "create"
25013
+ },
24769
25014
  "dayNight.getOptions": {
24770
25015
  capName: "day-night",
24771
25016
  capScope: "device",
@@ -29024,4 +29269,4 @@ function enumerateInferenceDevices(hw) {
29024
29269
  return out;
29025
29270
  }
29026
29271
  //#endregion
29027
- export { storageProviderCapability as $, filesystemBrowseCapability as A, sleep as At, logLevelAtMost as B, deviceStatusCapability as C, isDeviceConfigCap as Ct, enumerateSchemaFields as D, readinessKey as Dt, enumerateItemArrayFields as E, parseJsonUnknown as Et, isVoidInput as F, parseStreamParamsFormPatch as G, metricsProviderCapability as H, kebabToCamel as I, scoreRuntimes as J, platformProbeCapability as K, lifecycleJobSchema as L, isArrayOutputSchema as M, isCollectionArrayMethod as N, evaluateLinkExpression as O, resolveCapMount as Ot, isObjectInput as P, storageCapability as Q, localNetworkCapability as R, deviceStateCapability as S, hydrateSchema as St, enumerateInferenceDevices as T, parseJsonObject as Tt, normalizeUnit as U, looseSchema as V, objectInputDeclaresAddonId as W, settingsStoreCapability as X, setByPath as Y, snapshotCapability as Z, applyTransform as _, asString as _t, CAP_NAMES_WITH_STATUS as a, BaseAddon as at, buildStreamParamsConfigSchema as b, emitReadiness as bt, RUNTIME_DEFAULTS as c, DEVICE_STATUS_METHOD as ct, StorageLocationTypeSchema as d, DeviceType as dt, streamQualityLabel as et, UserRecordSchema as f, ReadinessRegistry as ft, alertsCapability as g, asNumber as gt, addonWidgetsCapability as h, asJsonObject as ht, BatteryStatusSchema as i, errMsg as it, getByPath as j, EventCategory as jt, extractNestedAddonId as k, scopeKey as kt, STREAM_PROFILE_META as l, DeviceFeature as lt, addonSettingsCapability as m, WELL_KNOWN_TAB_MAP as mt, AlertSchema as n, userManagementCapability as nt, DeviceStatusSchema as o, DATAPLANE_SECRET_HEADER as ot, addonPagesCapability as p, ReadinessTimeoutError as pt, procedureAuthKey as q, ApiKeyRecordSchema as r, validateExpressionSource as rt, METHOD_ACCESS_MAP as s, DEVICE_SETTINGS_CONTRIBUTION_METHODS as st, ALL_CAPABILITY_DEFINITIONS as t, toExpressionValue as tt, ScopedTokenSchema as u, DeviceRole as ut, authProviderCapability as v, createEvent as vt, doorbellCapability as w, nodePin as wt, deviceManagerCapability as x, expandCapMethods as xt, backupCapability as y, emitDownForOwnedCaps as yt, logDestinationCapability as z };
29272
+ export { storageCapability as $, extractNestedAddonId as A, scopeKey as At, logDestinationCapability as B, deviceStateCapability as C, hydrateSchema as Ct, enumerateItemArrayFields as D, parseJsonUnknown as Dt, enumerateInferenceDevices as E, parseJsonObject as Et, isObjectInput as F, objectInputDeclaresAddonId as G, looseSchema as H, isVoidInput as I, procedureAuthKey as J, parseStreamParamsFormPatch as K, kebabToCamel as L, getByPath as M, EventCategory as Mt, isArrayOutputSchema as N, enumerateSchemaFields as O, readinessKey as Ot, isCollectionArrayMethod as P, snapshotCapability as Q, lifecycleJobSchema as R, deviceManagerCapability as S, expandCapMethods as St, doorbellCapability as T, nodePin as Tt, metricsProviderCapability as U, logLevelAtMost as V, normalizeUnit as W, setByPath as X, scoreRuntimes as Y, settingsStoreCapability as Z, applyTransform as _, asNumber as _t, CAP_NAMES_WITH_STATUS as a, errMsg as at, buildStreamParamsConfigSchema as b, emitDownForOwnedCaps as bt, RUNTIME_DEFAULTS as c, DEVICE_SETTINGS_CONTRIBUTION_METHODS as ct, StorageLocationTypeSchema as d, DeviceRole as dt, storageProviderCapability as et, UserRecordSchema as f, DeviceType as ft, alertsCapability as g, asJsonObject as gt, addonWidgetsCapability as h, WELL_KNOWN_TAB_MAP as ht, BatteryStatusSchema as i, validateExpressionSource as it, filesystemBrowseCapability as j, sleep as jt, evaluateLinkExpression as k, resolveCapMount as kt, STREAM_PROFILE_META as l, DEVICE_STATUS_METHOD as lt, addonSettingsCapability as m, ReadinessTimeoutError as mt, AlertSchema as n, toExpressionValue as nt, DeviceStatusSchema as o, BaseAddon as ot, addonPagesCapability as p, ReadinessRegistry as pt, platformProbeCapability as q, ApiKeyRecordSchema as r, userManagementCapability as rt, METHOD_ACCESS_MAP as s, DATAPLANE_SECRET_HEADER as st, ALL_CAPABILITY_DEFINITIONS as t, streamQualityLabel as tt, ScopedTokenSchema as u, DeviceFeature as ut, authProviderCapability as v, asString as vt, deviceStatusCapability as w, isDeviceConfigCap as wt, dataStoreProviderCapability as x, emitReadiness as xt, backupCapability as y, createEvent as yt, localNetworkCapability as z };