@camstack/types 1.2.373 → 1.2.375

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 (40) hide show
  1. package/dist/addon.d.ts +2 -0
  2. package/dist/addon.js +6 -3
  3. package/dist/addon.mjs +5 -4
  4. package/dist/capabilities/addon-settings.cap.d.ts +10 -0
  5. package/dist/capabilities/core-blocks.cap.d.ts +2 -0
  6. package/dist/capabilities/device-manager.cap.d.ts +78 -0
  7. package/dist/capabilities/device-removal-hook.cap.d.ts +93 -0
  8. package/dist/capabilities/index.d.ts +6 -3
  9. package/dist/capabilities/keychain.cap.d.ts +11 -0
  10. package/dist/capabilities/local-network.cap.d.ts +62 -2
  11. package/dist/client.js +3 -0
  12. package/dist/client.mjs +3 -0
  13. package/dist/{composition-DCYnv4I6.js → composition-DIp0uE_b.js} +1 -1
  14. package/dist/{composition-C-WpVYTX.mjs → composition-EQ9Ok0Ee.mjs} +1 -1
  15. package/dist/device/device-removal-reconcile.d.ts +49 -0
  16. package/dist/device/device-type.d.ts +16 -0
  17. package/dist/{err-msg-DX6i_MY4.mjs → err-msg-DLerKiVO.mjs} +16 -0
  18. package/dist/{err-msg-Dx2Kor0g.js → err-msg-Ls8Q6dHO.js} +16 -0
  19. package/dist/generated/addon-api.d.ts +51 -0
  20. package/dist/generated/capability-router-map.d.ts +5 -2
  21. package/dist/generated/collection-array-methods.d.ts +1 -1
  22. package/dist/generated/method-access-map.d.ts +1 -1
  23. package/dist/generated/method-device-selectors.d.ts +2 -2
  24. package/dist/generated/system-proxy.d.ts +2 -2
  25. package/dist/i18n/camstack-error.d.ts +31 -0
  26. package/dist/i18n/translation.d.ts +39 -0
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.js +498 -25
  29. package/dist/index.mjs +470 -26
  30. package/dist/interfaces/addon.d.ts +11 -0
  31. package/dist/interfaces/config-ui.d.ts +20 -0
  32. package/dist/keychain/secrets-access.d.ts +12 -0
  33. package/dist/node.js +2 -2
  34. package/dist/node.mjs +2 -2
  35. package/dist/pipeline/face-rescore-schedule.d.ts +35 -0
  36. package/dist/{sleep-DAX0-2v9.mjs → sleep-DRqxtc0C.mjs} +62 -1
  37. package/dist/{sleep-DnQ5WsMI.js → sleep-rqlHXgwb.js} +91 -0
  38. package/dist/system/server-name.d.ts +7 -1
  39. package/dist/types/clip-model.d.ts +2 -1
  40. package/package.json +1 -1
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The reconcile half of `device-removal-hook` (D865), shared by every
3
+ * implementer so the rule is written once.
4
+ *
5
+ * A hook call can miss an implementer that was down or restarting when the
6
+ * device was deleted. At start (and every {@link REMOVAL_RECONCILE_INTERVAL_MS}
7
+ * after) the implementer asks device-manager for the TOMBSTONES it may have
8
+ * missed and runs its own idempotent removal for each.
9
+ *
10
+ * What it will never do: decide a device is gone because it is absent from a
11
+ * device list. The only input is a tombstone — a recorded DELETE. A failed
12
+ * read of the tombstones changes nothing (D49): it is logged and the next tick
13
+ * asks again.
14
+ */
15
+ import type { DeviceRemovedInput, DeviceRemovedResult } from '../capabilities/device-removal-hook.cap.js';
16
+ import type { DeviceTombstone } from '../capabilities/device-manager.cap.js';
17
+ import type { IScopedLogger } from '../interfaces/logging.js';
18
+ /** How often an implementer re-asks for tombstones after its start-up pass. */
19
+ export declare const REMOVAL_RECONCILE_INTERVAL_MS: number;
20
+ /** The slice of `ctx.api` the reconcile reads — narrower than the generated client. */
21
+ export interface TombstoneSource {
22
+ readonly deviceManager: {
23
+ readonly listDeletedSince: {
24
+ query(input: {
25
+ sinceMs: number;
26
+ }): Promise<readonly DeviceTombstone[]>;
27
+ };
28
+ };
29
+ }
30
+ export interface RemovalReconcileOptions {
31
+ readonly api: TombstoneSource | undefined;
32
+ readonly logger: IScopedLogger;
33
+ /** The implementer's own idempotent removal — the same one `onDeviceRemoved` runs. */
34
+ readonly remove: (input: DeviceRemovedInput) => Promise<DeviceRemovedResult>;
35
+ readonly now?: () => number;
36
+ }
37
+ export interface RemovalReconcileOutcome {
38
+ /** `false` when the tombstones could not be read; nothing was touched. */
39
+ readonly read: boolean;
40
+ readonly applied: number;
41
+ readonly failed: number;
42
+ }
43
+ /** One reconcile pass over every tombstone inside the retention window. */
44
+ export declare function reconcileRemovedDevices(opts: RemovalReconcileOptions): Promise<RemovalReconcileOutcome>;
45
+ /**
46
+ * Run the reconcile now and then periodically. Returns the disposer. The timer
47
+ * is unref'd and a pass never overlaps the previous one.
48
+ */
49
+ export declare function armRemovalReconcile(opts: RemovalReconcileOptions): () => void;
@@ -250,6 +250,22 @@ export declare enum DeviceRole {
250
250
  Nightvision = "nightvision",
251
251
  PrivacyMask = "privacy-mask",
252
252
  Doorbell = "doorbell",
253
+ /** Interior blind / shade / roller blind. HA `device_class: blind|shade`. */
254
+ CoverBlind = "cover-blind",
255
+ /** Exterior roller shutter. HA `device_class: shutter`; Homematic BROLL. */
256
+ CoverShutter = "cover-shutter",
257
+ /** Exterior awning. HA `device_class: awning`. */
258
+ CoverAwning = "cover-awning",
259
+ /** Curtain / drape. HA `device_class: curtain`. */
260
+ CoverCurtain = "cover-curtain",
261
+ /** Garage door. HA `device_class: garage`. A security actuator: exports gate it. */
262
+ CoverGarage = "cover-garage",
263
+ /** Gate. HA `device_class: gate`. A security actuator: exports gate it. */
264
+ CoverGate = "cover-gate",
265
+ /** Door. HA `device_class: door`. A security actuator: exports gate it. */
266
+ CoverDoor = "cover-door",
267
+ /** Window. HA `device_class: window`. */
268
+ CoverWindow = "cover-window",
253
269
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
254
270
  * real Switch device for UI rendering / export adapters. */
255
271
  BinaryHelper = "binary-helper",
@@ -254,6 +254,22 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
254
254
  DeviceRole["Nightvision"] = "nightvision";
255
255
  DeviceRole["PrivacyMask"] = "privacy-mask";
256
256
  DeviceRole["Doorbell"] = "doorbell";
257
+ /** Interior blind / shade / roller blind. HA `device_class: blind|shade`. */
258
+ DeviceRole["CoverBlind"] = "cover-blind";
259
+ /** Exterior roller shutter. HA `device_class: shutter`; Homematic BROLL. */
260
+ DeviceRole["CoverShutter"] = "cover-shutter";
261
+ /** Exterior awning. HA `device_class: awning`. */
262
+ DeviceRole["CoverAwning"] = "cover-awning";
263
+ /** Curtain / drape. HA `device_class: curtain`. */
264
+ DeviceRole["CoverCurtain"] = "cover-curtain";
265
+ /** Garage door. HA `device_class: garage`. A security actuator: exports gate it. */
266
+ DeviceRole["CoverGarage"] = "cover-garage";
267
+ /** Gate. HA `device_class: gate`. A security actuator: exports gate it. */
268
+ DeviceRole["CoverGate"] = "cover-gate";
269
+ /** Door. HA `device_class: door`. A security actuator: exports gate it. */
270
+ DeviceRole["CoverDoor"] = "cover-door";
271
+ /** Window. HA `device_class: window`. */
272
+ DeviceRole["CoverWindow"] = "cover-window";
257
273
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
258
274
  * real Switch device for UI rendering / export adapters. */
259
275
  DeviceRole["BinaryHelper"] = "binary-helper";
@@ -254,6 +254,22 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
254
254
  DeviceRole["Nightvision"] = "nightvision";
255
255
  DeviceRole["PrivacyMask"] = "privacy-mask";
256
256
  DeviceRole["Doorbell"] = "doorbell";
257
+ /** Interior blind / shade / roller blind. HA `device_class: blind|shade`. */
258
+ DeviceRole["CoverBlind"] = "cover-blind";
259
+ /** Exterior roller shutter. HA `device_class: shutter`; Homematic BROLL. */
260
+ DeviceRole["CoverShutter"] = "cover-shutter";
261
+ /** Exterior awning. HA `device_class: awning`. */
262
+ DeviceRole["CoverAwning"] = "cover-awning";
263
+ /** Curtain / drape. HA `device_class: curtain`. */
264
+ DeviceRole["CoverCurtain"] = "cover-curtain";
265
+ /** Garage door. HA `device_class: garage`. A security actuator: exports gate it. */
266
+ DeviceRole["CoverGarage"] = "cover-garage";
267
+ /** Gate. HA `device_class: gate`. A security actuator: exports gate it. */
268
+ DeviceRole["CoverGate"] = "cover-gate";
269
+ /** Door. HA `device_class: door`. A security actuator: exports gate it. */
270
+ DeviceRole["CoverDoor"] = "cover-door";
271
+ /** Window. HA `device_class: window`. */
272
+ DeviceRole["CoverWindow"] = "cover-window";
257
273
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
258
274
  * real Switch device for UI rendering / export adapters. */
259
275
  DeviceRole["BinaryHelper"] = "binary-helper";
@@ -50,6 +50,7 @@ import type { deviceHistoryCapability } from '../capabilities/device-history.cap
50
50
  import type { deviceManagerCapability } from '../capabilities/device-manager.cap.js';
51
51
  import type { deviceOpsCapability } from '../capabilities/device-ops.cap.js';
52
52
  import type { deviceProviderCapability } from '../capabilities/device-provider.cap.js';
53
+ import type { deviceRemovalHookCapability } from '../capabilities/device-removal-hook.cap.js';
53
54
  import type { deviceStateCapability } from '../capabilities/device-state.cap.js';
54
55
  import type { embeddingEncoderCapability } from '../capabilities/embedding-encoder.cap.js';
55
56
  import type { faceGalleryCapability } from '../capabilities/face-gallery.cap.js';
@@ -2787,6 +2788,20 @@ export type AppRouter = TrpcCoreRouter<{
2787
2788
  output: z.infer<typeof deviceManagerCapability.methods.remove.output>;
2788
2789
  meta: object;
2789
2790
  }>;
2791
+ listDeletedSince: TRPCQueryProcedure<{
2792
+ input: {
2793
+ [x: string]: unknown;
2794
+ } & z.input<typeof deviceManagerCapability.methods.listDeletedSince.input>;
2795
+ output: z.infer<typeof deviceManagerCapability.methods.listDeletedSince.output>;
2796
+ meta: object;
2797
+ }>;
2798
+ cleanupDeletedDevicesData: TRPCMutationProcedure<{
2799
+ input: {
2800
+ [x: string]: unknown;
2801
+ } & z.input<typeof deviceManagerCapability.methods.cleanupDeletedDevicesData.input>;
2802
+ output: z.infer<typeof deviceManagerCapability.methods.cleanupDeletedDevicesData.output>;
2803
+ meta: object;
2804
+ }>;
2790
2805
  removeByIntegration: TRPCMutationProcedure<{
2791
2806
  input: {
2792
2807
  [x: string]: unknown;
@@ -3233,6 +3248,28 @@ export type AppRouter = TrpcCoreRouter<{
3233
3248
  meta: object;
3234
3249
  }>;
3235
3250
  }>>;
3251
+ deviceRemovalHook: TRPCBuiltRouter<{
3252
+ ctx: TrpcContext;
3253
+ meta: object;
3254
+ errorShape: AugmentedErrorShape;
3255
+ transformer: true;
3256
+ }, TRPCDecorateCreateRouterOptions<{
3257
+ onDeviceRemoved: TRPCMutationProcedure<{
3258
+ input: {
3259
+ [x: string]: unknown;
3260
+ } & z.input<typeof deviceRemovalHookCapability.methods.onDeviceRemoved.input>;
3261
+ output: z.infer<typeof deviceRemovalHookCapability.methods.onDeviceRemoved.output>;
3262
+ meta: object;
3263
+ }>;
3264
+ listDeviceData: TRPCQueryProcedure<{
3265
+ input: {
3266
+ nodeId?: string | undefined;
3267
+ addonId?: string | undefined;
3268
+ } | undefined;
3269
+ output: z.infer<typeof deviceRemovalHookCapability.methods.listDeviceData.output>;
3270
+ meta: object;
3271
+ }>;
3272
+ }>>;
3236
3273
  deviceState: TRPCBuiltRouter<{
3237
3274
  ctx: TrpcContext;
3238
3275
  meta: object;
@@ -3886,6 +3923,13 @@ export type AppRouter = TrpcCoreRouter<{
3886
3923
  output: z.infer<typeof keychainCapability.methods.delete.output>;
3887
3924
  meta: object;
3888
3925
  }>;
3926
+ deleteDeviceScope: TRPCMutationProcedure<{
3927
+ input: {
3928
+ [x: string]: unknown;
3929
+ } & z.input<typeof keychainCapability.methods.deleteDeviceScope.input>;
3930
+ output: z.infer<typeof keychainCapability.methods.deleteDeviceScope.output>;
3931
+ meta: object;
3932
+ }>;
3889
3933
  listMeta: TRPCQueryProcedure<{
3890
3934
  input: {
3891
3935
  [x: string]: unknown;
@@ -4417,6 +4461,13 @@ export type AppRouter = TrpcCoreRouter<{
4417
4461
  output: z.infer<typeof localNetworkCapability.methods.downloadCa.output>;
4418
4462
  meta: object;
4419
4463
  }>;
4464
+ useStoredUploadedCertificate: TRPCMutationProcedure<{
4465
+ input: {
4466
+ nodeId?: string | undefined;
4467
+ } | undefined;
4468
+ output: z.infer<typeof localNetworkCapability.methods.useStoredUploadedCertificate.output>;
4469
+ meta: object;
4470
+ }>;
4420
4471
  revertToGeneratedCertificate: TRPCMutationProcedure<{
4421
4472
  input: {
4422
4473
  nodeId?: string | undefined;
@@ -56,6 +56,7 @@ export { deviceHistoryCapability } from '../capabilities/device-history.cap.js';
56
56
  export { deviceManagerCapability } from '../capabilities/device-manager.cap.js';
57
57
  export { deviceOpsCapability } from '../capabilities/device-ops.cap.js';
58
58
  export { deviceProviderCapability } from '../capabilities/device-provider.cap.js';
59
+ export { deviceRemovalHookCapability } from '../capabilities/device-removal-hook.cap.js';
59
60
  export { deviceStateCapability } from '../capabilities/device-state.cap.js';
60
61
  export { deviceStatusCapability } from '../capabilities/device-status.cap.js';
61
62
  export { doorbellCapability } from '../capabilities/doorbell.cap.js';
@@ -230,6 +231,7 @@ export declare const CAPABILITY_NAMES: {
230
231
  readonly deviceManager: 'device-manager';
231
232
  readonly deviceOps: 'device-ops';
232
233
  readonly deviceProvider: 'device-provider';
234
+ readonly deviceRemovalHook: 'device-removal-hook';
233
235
  readonly deviceState: 'device-state';
234
236
  readonly deviceStatus: 'device-status';
235
237
  readonly doorbell: 'doorbell';
@@ -417,6 +419,7 @@ export interface CapabilityRouterMap<TRouter = unknown> {
417
419
  readonly deviceManager: TRouter;
418
420
  readonly deviceOps: TRouter;
419
421
  readonly deviceProvider: TRouter;
422
+ readonly deviceRemovalHook: TRouter;
420
423
  readonly deviceState: TRouter;
421
424
  readonly deviceStatus: TRouter;
422
425
  readonly doorbell: TRouter;
@@ -537,8 +540,8 @@ export interface CapabilityRouterMap<TRouter = unknown> {
537
540
  export declare const SINGLETON_CAPABILITY_NAMES: readonly ['accessories', 'addon-pages', 'addon-settings', 'addon-widgets', 'addons', 'admin-ui', 'air-quality-sensor', 'alarm-panel', 'alerts', 'ambient-light-sensor', 'audio-analysis', 'audio-analyzer', 'audio-codec', 'audio-metrics', 'automation-control', 'backup', 'battery', 'binary', 'brightness', 'button', 'calendars', 'camera-credentials', 'camera-grid-layout', 'camera-pipeline-config', 'camera-streams', 'carbon-monoxide', 'climate-control', 'color', 'composer', 'connectivity', 'consumables', 'contact', 'control', 'core-blocks', 'cover', 'database-snapshot', 'day-night', 'decoder', 'detection-pipeline', 'device-admin-link', 'device-adoption', 'device-credentials', 'device-discovery', 'device-history', 'device-manager', 'device-ops', 'device-state', 'device-status', 'doorbell', 'enum-sensor', 'event-emitter', 'face-gallery', 'fan-control', 'feature-probe', 'filesystem-browse', 'flood', 'gas', 'humidifier', 'humidity-sensor', 'image', 'image-settings', 'integrations', 'intercom', 'keychain', 'keychain-admin', 'lawn-mower-control', 'llm-runtime', 'local-network', 'lock-control', 'media-player', 'metrics-provider', 'model-convert', 'model-distributor', 'motion', 'motion-detection', 'motion-trigger', 'motion-zones', 'native-object-detection', 'navigation', 'network-link', 'network-quality', 'node-certificates', 'nodes', 'notification-rules', 'notifier', 'numeric-sensor', 'oidc-connections', 'osd', 'osd-manager', 'pet-feeder', 'pipeline-analytics', 'pipeline-executor', 'pipeline-orchestrator', 'pipeline-runner', 'plate-gallery', 'platform-probe', 'power-meter', 'presence', 'pressure-sensor', 'privacy-mask', 'ptz', 'ptz-autotrack', 'reboot', 'recording-archive', 'recording-export', 'recording-onboard', 'recording-signal', 'scene-monitor', 'script-runner', 'server-management', 'settings-store', 'smoke', 'snapshot', 'sso-bridge', 'storage', 'storage-migration', 'stream-broker', 'stream-catalog', 'stream-params', 'stream-signals', 'switch', 'system', 'tamper', 'temperature-sensor', 'terminal-session', 'toast', 'training', 'update', 'user-management', 'vacuum-control', 'valve', 'vector-store', 'vibration', 'viewer-ui', 'water-heater', 'weather', 'webrtc-session', 'zone-analytics', 'zone-rules', 'zones'];
538
541
  /** Union of singleton capability names (literal string union). */
539
542
  export type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number];
540
- /** Capability names whose mode is `collection` (33 caps). */
541
- export declare const COLLECTION_CAPABILITY_NAMES: readonly ['addon-pages-source', 'addon-routes', 'addon-widgets-source', 'auth-provider', 'broker', 'calendar-source', 'connection-test', 'custom-model-registry', 'data-store-provider', 'device-export', 'device-extension', 'device-provider', 'embedding-encoder', 'failure-contribution', 'llm', 'load-contribution', 'log-channels', 'log-destination', 'login-method', 'mesh-network', 'mqtt-broker', 'network-access', 'notification-output', 'oauth-integration', 'recording', 'smtp-provider', 'storage-evictable', 'storage-occupancy', 'storage-provider', 'training-provider', 'turn-provider', 'user-passkeys', 'videoclips'];
543
+ /** Capability names whose mode is `collection` (34 caps). */
544
+ export declare const COLLECTION_CAPABILITY_NAMES: readonly ['addon-pages-source', 'addon-routes', 'addon-widgets-source', 'auth-provider', 'broker', 'calendar-source', 'connection-test', 'custom-model-registry', 'data-store-provider', 'device-export', 'device-extension', 'device-provider', 'device-removal-hook', 'embedding-encoder', 'failure-contribution', 'llm', 'load-contribution', 'log-channels', 'log-destination', 'login-method', 'mesh-network', 'mqtt-broker', 'network-access', 'notification-output', 'oauth-integration', 'recording', 'smtp-provider', 'storage-evictable', 'storage-occupancy', 'storage-provider', 'training-provider', 'turn-provider', 'user-passkeys', 'videoclips'];
542
545
  /** Union of collection capability names (literal string union). */
543
546
  export type CollectionCapabilityName = typeof COLLECTION_CAPABILITY_NAMES[number];
544
547
  /** Capability mode lookup at runtime — mirrors the `.cap.ts` definitions. */
@@ -8,7 +8,7 @@
8
8
  * barrel (`ALL_CAPABILITY_DEFINITIONS`), which would cost ~144MB RSS per
9
9
  * forked runner. See docs/decisions/adr-0028.md.
10
10
  *
11
- * Coverage: 26 collection caps, 45 array methods.
11
+ * Coverage: 27 collection caps, 46 array methods.
12
12
  */
13
13
  export declare const COLLECTION_ARRAY_METHODS: Readonly<Record<string, readonly string[]>>;
14
14
  /**
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 1332 method paths across 173 capabilities.
9
+ * Coverage: 1338 method paths across 174 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -6,8 +6,8 @@
6
6
  * system-scope cap that takes a deviceId was previously never device-filtered
7
7
  * — see the generator header).
8
8
  *
9
- * Coverage: 524 methods carry a device reference, of which
10
- * 169 are on SYSTEM-scope caps.
9
+ * Coverage: 526 methods carry a device reference, of which
10
+ * 171 are on SYSTEM-scope caps.
11
11
  *
12
12
  * Top-level fields, number arrays, and one-level arrays of objects carrying
13
13
  * a numeric device field (targets[].deviceId) are all mapped; the matcher
@@ -78,14 +78,14 @@ export interface SystemProxy {
78
78
  readonly deviceCredentials: Pick<InferProvider<typeof deviceCredentialsCapability>, 'listDeviceCredentials' | 'startEnrollment' | 'revokeDeviceCredential' | 'getDeviceCertificateSettings' | 'setDeviceCertificateSettings' | 'deleteDeviceCredential' | 'getDeviceCaStatus' | 'renameDeviceCredential'>;
79
79
  readonly deviceExport: Pick<InferProvider<typeof deviceExportCapability>, 'getStatus' | 'listSupportedDeviceKinds' | 'listExposedDevices' | 'exposeDevice' | 'unexposeDevice'>;
80
80
  readonly deviceHistory: Pick<InferProvider<typeof deviceHistoryCapability>, 'listNodeSeries' | 'queryNode' | 'declareSeries' | 'record' | 'recordBuckets' | 'getStatus'>;
81
- readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'migrateDevice' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'getRoleDisplayDefaults' | 'setRoleDisplayDefaults' | 'listLocations' | 'addLocation' | 'removeLocation' | 'renameLocation' | 'listLocationIcons' | 'setLocationIcon' | 'listLocationDescriptions' | 'setLocationDescription' | 'listSiteZones' | 'setSiteZone' | 'removeSiteZone' | 'renameSiteZone' | 'setLocationZone' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'getChildrenBatch' | 'getLinkedDevicesBatch' | 'removeByIntegration' | 'getBindingsBatch' | 'getAllBindings' | 'listDeviceIdsByCaps' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField' | 'adoptionListCandidateFilters' | 'adoptionListCandidates' | 'adoptionRefresh' | 'adoptionAdopt' | 'adoptionRelease' | 'adoptionStartJob' | 'adoptionListJobs' | 'adoptionCancelJob' | 'adoptionResync' | 'discoveryProviders' | 'discoverAllProviders' | 'discoverProvider' | 'providerCreationType' | 'providerDiscoveryParamsSchema' | 'getDeviceStatusAggregateBatch'>;
81
+ readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'migrateDevice' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'getRoleDisplayDefaults' | 'setRoleDisplayDefaults' | 'listLocations' | 'addLocation' | 'removeLocation' | 'renameLocation' | 'listLocationIcons' | 'setLocationIcon' | 'listLocationDescriptions' | 'setLocationDescription' | 'listSiteZones' | 'setSiteZone' | 'removeSiteZone' | 'renameSiteZone' | 'setLocationZone' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'getChildrenBatch' | 'getLinkedDevicesBatch' | 'listDeletedSince' | 'cleanupDeletedDevicesData' | 'removeByIntegration' | 'getBindingsBatch' | 'getAllBindings' | 'listDeviceIdsByCaps' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField' | 'adoptionListCandidateFilters' | 'adoptionListCandidates' | 'adoptionRefresh' | 'adoptionAdopt' | 'adoptionRelease' | 'adoptionStartJob' | 'adoptionListJobs' | 'adoptionCancelJob' | 'adoptionResync' | 'discoveryProviders' | 'discoverAllProviders' | 'discoverProvider' | 'providerCreationType' | 'providerDiscoveryParamsSchema' | 'getDeviceStatusAggregateBatch'>;
82
82
  readonly deviceProvider: Pick<InferProvider<typeof deviceProviderCapability>, 'start' | 'stop' | 'getStatus' | 'getDevices' | 'reloadDevice' | 'supportsDiscovery' | 'discoverDevices' | 'getDiscoveryParamsSchema' | 'getManualCreationType' | 'adoptDiscoveredDevice' | 'supportsManualCreation' | 'getChildCreationSchema' | 'createDevice' | 'testCreationField'>;
83
83
  readonly deviceState: Pick<InferProvider<typeof deviceStateCapability>, 'getAllSnapshots' | 'listClaims'>;
84
84
  readonly faceGallery: Pick<InferProvider<typeof faceGalleryCapability>, 'listIdentities' | 'createIdentity' | 'renameIdentity' | 'deleteIdentity' | 'listIdentitySamples' | 'auditIdentitySamples' | 'removeSample' | 'getFaceMedia' | 'assignFace' | 'unassignFace' | 'deleteFace' | 'assignFaces' | 'unassignFaces' | 'suggestFaceClusters'>;
85
85
  readonly integrations: Pick<InferProvider<typeof integrationsCapability>, 'list' | 'get' | 'getByAddonId' | 'create' | 'update' | 'delete' | 'getSettings' | 'setSettings' | 'getAvailableTypes' | 'testConnection'>;
86
86
  readonly keychainAdmin: Pick<InferProvider<typeof keychainAdminCapability>, 'status' | 'listSecrets' | 'listAudit' | 'reveal' | 'setSystemSecret' | 'deleteOrphans' | 'rotateMasterKey' | 'purgeRetiredKeys' | 'downloadRecoveryKey' | 'resetKeychain' | 'resetReport' | 'acknowledgeReset'>;
87
87
  readonly llm: Pick<InferProvider<typeof llmCapability>, 'generate' | 'generateVision' | 'cancel' | 'listProfileKinds' | 'listProfiles' | 'upsertProfile' | 'deleteProfile' | 'testProfile' | 'listModels' | 'getDefaults' | 'setDefault' | 'getUsage' | 'listModelCatalog' | 'listRuntimeNodes' | 'listNodeModels' | 'resolveModelRef' | 'installModel' | 'deleteModel' | 'getRuntimeStatus' | 'startRuntime' | 'stopRuntime'>;
88
- readonly localNetwork: Pick<InferProvider<typeof localNetworkCapability>, 'list' | 'getPreferred' | 'getConnectionEndpoints' | 'getNotificationEndpoint' | 'setNotificationEndpoint' | 'getViewerEndpoints' | 'setViewerEndpoints' | 'getAddresses' | 'addCustomAddress' | 'removeCustomAddress' | 'setAddressRole' | 'getHubAddresses' | 'getAllowedAddresses' | 'setAllowedAddresses' | 'resetAllowlistToBestMatch' | 'getTlsStatus' | 'regenerateCertificate' | 'uploadCertificate' | 'downloadCa' | 'revertToGeneratedCertificate'>;
88
+ readonly localNetwork: Pick<InferProvider<typeof localNetworkCapability>, 'list' | 'getPreferred' | 'getConnectionEndpoints' | 'getNotificationEndpoint' | 'setNotificationEndpoint' | 'getViewerEndpoints' | 'setViewerEndpoints' | 'getAddresses' | 'addCustomAddress' | 'removeCustomAddress' | 'setAddressRole' | 'getHubAddresses' | 'getAllowedAddresses' | 'setAllowedAddresses' | 'resetAllowlistToBestMatch' | 'getTlsStatus' | 'regenerateCertificate' | 'uploadCertificate' | 'downloadCa' | 'useStoredUploadedCertificate' | 'revertToGeneratedCertificate'>;
89
89
  readonly meshNetwork: Pick<InferProvider<typeof meshNetworkCapability>, 'getStatus' | 'join' | 'startLogin' | 'leave' | 'logout' | 'listPeers' | 'testConnection'>;
90
90
  readonly metricsProvider: Pick<InferProvider<typeof metricsProviderCapability>, 'collectSnapshot' | 'getCached' | 'getCurrent' | 'getDiskSpace' | 'getGpuInfo' | 'getCpuTemperature' | 'getProcessStats' | 'listAddonInstances' | 'getAddonStats' | 'listNodeProcesses' | 'getLoadSeries'>;
91
91
  readonly mqttBroker: Pick<InferProvider<typeof mqttBrokerCapability>, 'listBrokers' | 'getBrokerConfig' | 'addBroker' | 'removeBroker' | 'testConnection' | 'startEmbeddedBroker' | 'stopEmbeddedBroker' | 'getStatus'>;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A user-facing error with a STABLE code (D863).
3
+ *
4
+ * `message` is always the English text, so every consumer that knows nothing
5
+ * of codes (old clients, logs, the mesh) behaves exactly as before. The hub's
6
+ * tRPC error formatter reads `code` + `params` and, when the request language
7
+ * has a text for `server:<code>`, replaces the response `message`; the code
8
+ * stays in the payload (`data.i18n`).
9
+ */
10
+ import { z } from 'zod';
11
+ import type { TranslationParams } from './translation.js';
12
+ /** Dotted lower-case code, e.g. `auth.invalid-credentials`. It is the key in the `server` catalog. */
13
+ export declare const ErrorCodeSchema: z.ZodString;
14
+ /** What travels in the error payload next to the message. */
15
+ export declare const ErrorI18nPayloadSchema: z.ZodObject<{
16
+ code: z.ZodString;
17
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
18
+ }, z.core.$strip>;
19
+ export type ErrorI18nPayload = z.infer<typeof ErrorI18nPayloadSchema>;
20
+ export declare class CamstackError extends Error {
21
+ readonly i18nCode: string;
22
+ readonly i18nParams: TranslationParams | undefined;
23
+ constructor(code: string, params: TranslationParams | undefined, englishMessage: string);
24
+ }
25
+ /** `throw userError('device.not-found', { id }, 'Device 12 not found')` */
26
+ export declare function userError(code: string, params: TranslationParams | undefined, englishFallback: string): CamstackError;
27
+ /**
28
+ * Finds a code on `err` or anywhere down its `.cause` chain. Duck-typed on
29
+ * the field so it survives a module boundary (self-contained addons).
30
+ */
31
+ export declare function readErrorI18n(err: unknown): ErrorI18nPayload | null;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Server-side translation primitives (D863) - pure, zod only.
3
+ *
4
+ * A catalog is a FLAT `Record<key, string>` per (namespace, language). A
5
+ * reference is `"<namespace>:<key>"`; the English text always travels next to
6
+ * it (`label` beside `labelKey`), so a missing key or an unknown language is
7
+ * the English text, never a blank or a raw key.
8
+ */
9
+ import { z } from 'zod';
10
+ /** The languages a catalog may be written in. English is the mandatory base. */
11
+ export declare const CatalogLangSchema: z.ZodEnum<{
12
+ en: "en";
13
+ it: "it";
14
+ }>;
15
+ export type CatalogLang = z.infer<typeof CatalogLangSchema>;
16
+ export declare const CATALOG_LANGS: readonly CatalogLang[];
17
+ export declare const DEFAULT_CATALOG_LANG: CatalogLang;
18
+ /** One catalog file: flat key to text. A file of any other shape is rejected whole. */
19
+ export declare const CatalogFileSchema: z.ZodRecord<z.ZodString, z.ZodString>;
20
+ export type CatalogFile = z.infer<typeof CatalogFileSchema>;
21
+ /** `{name}` placeholders in a catalog text. */
22
+ export type TranslationParams = Readonly<Record<string, string | number>>;
23
+ /** Fills `{name}` placeholders; an unknown placeholder is left as written. */
24
+ export declare function interpolate(template: string, params?: TranslationParams): string;
25
+ /** Splits `"ns:key"`; `null` when the reference has no namespace. */
26
+ export declare function splitTranslationRef(ref: string): {
27
+ ns: string;
28
+ key: string;
29
+ } | null;
30
+ /** `(namespace, key) -> text in the request language`, or `undefined` when absent. */
31
+ export type CatalogLookup = (ns: string, key: string) => string | undefined;
32
+ /**
33
+ * Returns `value` with every `labelKey` / `descriptionKey` / `titleKey` that
34
+ * the catalog can resolve replaced into `label` / `description` / `title`.
35
+ * Pure: the input is never mutated; a subtree with nothing to change is
36
+ * returned as the SAME object. A key the catalog does not hold keeps the
37
+ * English text that sits next to it.
38
+ */
39
+ export declare function localizeConfigTree(value: unknown, lookup: CatalogLookup): unknown;
package/dist/index.d.ts CHANGED
@@ -273,6 +273,10 @@ export type { StateLabel, StateLabelKey, StateLabelLocale } from './i18n/state-l
273
273
  export { isStateLabelKey, STATE_LABEL_KEYS, STATE_LABELS, stateLabel, } from './i18n/state-labels.js';
274
274
  export type { EventKindLabel, EventKindLabelKey, EventKindLabelLocale, } from './i18n/event-kind-labels.js';
275
275
  export { EVENT_KIND_LABEL_KEYS, EVENT_KIND_LABELS, eventKindLabel, isEventKindLabelKey, } from './i18n/event-kind-labels.js';
276
+ export type { CatalogFile, CatalogLang, CatalogLookup, TranslationParams, } from './i18n/translation.js';
277
+ export { CATALOG_LANGS, CatalogFileSchema, CatalogLangSchema, DEFAULT_CATALOG_LANG, interpolate, localizeConfigTree, splitTranslationRef, } from './i18n/translation.js';
278
+ export type { ErrorI18nPayload } from './i18n/camstack-error.js';
279
+ export { CamstackError, ErrorCodeSchema, ErrorI18nPayloadSchema, readErrorI18n, userError, } from './i18n/camstack-error.js';
276
280
  export { assertTimelapseCadences, DEFAULT_TIMELAPSE_PREVIEW_TEXT, readTimelapseGeneratedAt, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleInputSchema, TimelapseRulePatchSchema, TimelapseRuleSchema, TimelapseTemplateSchema, } from './notification/timelapse-rule.js';
277
281
  export { CLUSTER_MODEL_SCOPED_STEPS, CLUSTER_MODEL_SECTION_ID, CLUSTER_STEP_SETTING_FIELDS, type ClusterModelScopedStep, type ClusterStepModels, type ClusterStepSettingField, type ClusterStepSettings, clusterModelSettingKey, clusterStepSettingFieldsFor, clusterStepSettingKey, DEFAULT_CLUSTER_STEP_MODELS, DEFAULT_CLUSTER_STEP_SETTINGS, DEFAULT_MIN_LANDMARK_FACE_SIZE_PX, type HydratedClusterSection, type HydratedClusterView, interpretStoredClusterModel, type InvalidClusterStepModelEntry, invalidClusterStepModelEntries, isClusterScopedStep, overlayClusterStepSettings, pickClusterStepModels, pickClusterStepSettings, pickInvalidClusterStepModels, readClusterStepModels, readClusterStepSettings, resolveClusterStepModelId, type StepModelScope, type StoredClusterModelInterpretation, } from './pipeline/cluster-model-scope.js';
278
282
  export { CAMERA_SENSORS_NOT_LOADED, CAMERA_SENSORS_SETTINGS_KEY, CAMERA_TRIGGER, type CameraSensorAttachment, CameraSensorAttachmentSchema, type CameraSensorRef, CameraSensorRefSchema, cameraSensorRefKey, type CameraSensorsConfig, CameraSensorsConfigSchema, type CameraOwnMotion, CameraOwnMotionSchema, type CameraRawLevel, CameraRawLevelSchema, type CameraSensorEntry, CameraSensorEntrySchema, type CameraSensorMode, CameraSensorModeSchema, type CameraSensorsNotEnforced, CameraSensorsNotEnforcedSchema, type CameraSensorsNotForwarded, CameraSensorsNotForwardedSchema, type CameraSensorsStatus, CameraSensorsStatusSchema, DEFAULT_CAMERA_SENSOR_MODE, MAX_CAMERA_SENSORS, type MotionTriggeredBy, type MotionTriggeredByReading, MotionTriggeredBySchema, readMotionTriggeredBy, } from './pipeline/camera-sensors.js';
@@ -288,6 +292,7 @@ export * from './pipeline/load-balancing/index.js';
288
292
  export * from './pipeline/node-benchmark/index.js';
289
293
  export { deriveRootFaceRefineRect, ROOT_FACE_REFINE_INPUT_PX, ROOT_FACE_REFINE_SCALE, } from './pipeline/root-face-crop.js';
290
294
  export { DEFAULT_DETAIL_CROP_CONVENTION, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, type DetailCropConvention, DetailCropConventionSchema, type DetailCropRect, deriveDetailCropRect, FULL_IMAGE_BBOX, type HydratedSettingsSection, type HydratedSettingsView, pickDetailCropConvention, readDetailCropConvention, } from './pipeline/detail-crop.js';
295
+ export { FACE_RESCORE_INTERVAL_FIELD, FACE_RESCORE_INTERVAL_KEY, FACE_RESCORE_INTERVAL_MIN_RUNNING, FACE_RESCORE_SECTION_ID, type FaceRescoreSettingsView, pickFaceRescoreIntervalMinutes, readFaceRescoreIntervalMinutes, } from './pipeline/face-rescore-schedule.js';
291
296
  export { DEFAULT_NATIVE_LEASE_SETTINGS, NATIVE_LEASE_ACTIVITY_FIELD, NATIVE_LEASE_ACTIVITY_KEY, NATIVE_LEASE_ADMISSION_FIELD, NATIVE_LEASE_ADMISSION_KEY, NATIVE_LEASE_BUDGET_FIELD, NATIVE_LEASE_BUDGET_KEY, NATIVE_LEASE_HOLD_FIELD, NATIVE_LEASE_HOLD_KEY, NATIVE_LEASE_SCENE_BUDGET_FIELD, NATIVE_LEASE_SCENE_BUDGET_KEY, NATIVE_LEASE_SECTION_ID, NATIVE_LEASE_TILE_BUDGET_FIELD, NATIVE_LEASE_TILE_BUDGET_KEY, type NativeLeaseAdmission, NativeLeaseAdmissionSchema, type NativeLeaseKnob, type NativeLeaseNumberKnob, type NativeLeaseSettings, type NativeLeaseSettingsOverride, NativeLeaseSettingsSchema, pickNativeLeaseOverride, readNativeLeaseOverride, } from './pipeline/native-lease.js';
292
297
  export { ACCESS_ROLES, type AccessRoleAssignment, type AccessRoleId, type AccessRoleSpec, buildRoleScopes, detectAccessRole, roleSpec, } from './schemas/access-roles.js';
293
298
  export { type ApiKeyRecord, ApiKeyRecordSchema, type CapScope, CapScopeSchema, type DeviceSelector, DeviceSelectorSchema, type DeviceTokenScope, type MethodAccess, MethodAccessSchema, type ScopedToken, ScopedTokenSchema, type TokenScope, TokenScopeSchema, type UserRecord, UserRecordSchema, } from './schemas/auth-records.js';
@@ -322,3 +327,4 @@ export type { SiteZone } from './device/site-zone.js';
322
327
  export { SiteZoneSchema, siteZoneKey } from './device/site-zone.js';
323
328
  export type { ServerNameInfo } from './system/server-name.js';
324
329
  export { resolveServerName, SERVER_NAME_MAX_LENGTH, SERVER_NAME_SETTING_KEY, ServerNameInfoSchema, ServerNameSchema, shortHostname, } from './system/server-name.js';
330
+ export { armRemovalReconcile, reconcileRemovedDevices, REMOVAL_RECONCILE_INTERVAL_MS, type RemovalReconcileOptions, type RemovalReconcileOutcome, type TombstoneSource, } from './device/device-removal-reconcile.js';