@camstack/addon-post-analysis 1.2.369 → 1.2.370

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 (15) hide show
  1. package/dist/{clip-model-registry-E4CGZ8NR.js → clip-model-registry-C3AUTkBR.js} +1618 -45
  2. package/dist/{clip-model-registry-C_-tWzrX.mjs → clip-model-registry-CCwyUQ7k.mjs} +1595 -46
  3. package/dist/embedding-encoder/index.js +1 -1
  4. package/dist/embedding-encoder/index.mjs +1 -1
  5. package/dist/pipeline-analytics/_stub.js +752 -631
  6. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Bac17NNv.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-C1gR-74b.mjs} +3 -3
  7. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BRMRfKVO.mjs +26 -0
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CkaRW2Sy.mjs +26 -0
  9. package/dist/pipeline-analytics/{hostInit-CMFNXHOl.mjs → hostInit-s-NoTpFK.mjs} +3 -3
  10. package/dist/pipeline-analytics/index.js +982 -82
  11. package/dist/pipeline-analytics/index.mjs +1013 -113
  12. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  13. package/package.json +5 -1
  14. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DOGD-EFh.mjs +0 -26
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Bb1tsxlC.mjs +0 -26
@@ -5490,7 +5490,7 @@ var ZodIssueCode = {
5490
5490
  var ZodFirstPartyTypeKind;
5491
5491
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5492
5492
  //#endregion
5493
- //#region ../types/dist/sleep-BBF1iXUi.mjs
5493
+ //#region ../types/dist/sleep-DRqxtc0C.mjs
5494
5494
  /**
5495
5495
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5496
5496
  * window to float samples (D455).
@@ -8517,6 +8517,10 @@ var DEVICE_SCOPED_CAPS = new Set([
8517
8517
  function isDeviceScopedCap(capName) {
8518
8518
  return DEVICE_SCOPED_CAPS.has(capName);
8519
8519
  }
8520
+ object({
8521
+ code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
8522
+ params: record(string(), union([string(), number()])).optional()
8523
+ });
8520
8524
  function hfModelUrl(repo, path) {
8521
8525
  return `https://huggingface.co/${repo}/resolve/main/${path}`;
8522
8526
  }
@@ -8545,7 +8549,7 @@ function sleep(ms) {
8545
8549
  return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
8546
8550
  }
8547
8551
  //#endregion
8548
- //#region ../types/dist/err-msg-DX6i_MY4.mjs
8552
+ //#region ../types/dist/err-msg-DLerKiVO.mjs
8549
8553
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
8550
8554
  DeviceType["Camera"] = "camera";
8551
8555
  DeviceType["Hub"] = "hub";
@@ -8795,6 +8799,22 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8795
8799
  DeviceRole["Nightvision"] = "nightvision";
8796
8800
  DeviceRole["PrivacyMask"] = "privacy-mask";
8797
8801
  DeviceRole["Doorbell"] = "doorbell";
8802
+ /** Interior blind / shade / roller blind. HA `device_class: blind|shade`. */
8803
+ DeviceRole["CoverBlind"] = "cover-blind";
8804
+ /** Exterior roller shutter. HA `device_class: shutter`; Homematic BROLL. */
8805
+ DeviceRole["CoverShutter"] = "cover-shutter";
8806
+ /** Exterior awning. HA `device_class: awning`. */
8807
+ DeviceRole["CoverAwning"] = "cover-awning";
8808
+ /** Curtain / drape. HA `device_class: curtain`. */
8809
+ DeviceRole["CoverCurtain"] = "cover-curtain";
8810
+ /** Garage door. HA `device_class: garage`. A security actuator: exports gate it. */
8811
+ DeviceRole["CoverGarage"] = "cover-garage";
8812
+ /** Gate. HA `device_class: gate`. A security actuator: exports gate it. */
8813
+ DeviceRole["CoverGate"] = "cover-gate";
8814
+ /** Door. HA `device_class: door`. A security actuator: exports gate it. */
8815
+ DeviceRole["CoverDoor"] = "cover-door";
8816
+ /** Window. HA `device_class: window`. */
8817
+ DeviceRole["CoverWindow"] = "cover-window";
8798
8818
  /** Virtual HA toggle (input_boolean.*) — distinguishable from a
8799
8819
  * real Switch device for UI rendering / export adapters. */
8800
8820
  DeviceRole["BinaryHelper"] = "binary-helper";
@@ -8875,7 +8895,7 @@ function errMsg(err) {
8875
8895
  return String(err);
8876
8896
  }
8877
8897
  //#endregion
8878
- //#region ../types/dist/composition-C-WpVYTX.mjs
8898
+ //#region ../types/dist/composition-EQ9Ok0Ee.mjs
8879
8899
  /**
8880
8900
  * Deterministic SHA-256 hash of an arbitrary serialisable value. The
8881
8901
  * canonical form sorts object keys alphabetically at every depth so two
@@ -13436,6 +13456,177 @@ var ConvertResultSchema = object({
13436
13456
  files: array(string()).readonly()
13437
13457
  })).readonly()
13438
13458
  });
13459
+ _enum(["new-session", "step-up"]);
13460
+ /** The languages the hub's app landing pages are written in (D858). */
13461
+ var AppPageLangSchema = _enum(["en", "it"]);
13462
+ /** How a native app starts one login method (D858), as `auth.listLoginMethods` reports it. */
13463
+ var AppLoginPathSchema = discriminatedUnion("kind", [object({ kind: literal("native") }), object({
13464
+ kind: literal("browser"),
13465
+ startPath: string().startsWith("/")
13466
+ })]);
13467
+ /**
13468
+ * Device certificates (D855) — the wire contract shared by the hub, the admin
13469
+ * UI and the native viewer.
13470
+ *
13471
+ * A device (a phone) generates its OWN P-256 key pair in hardware (Secure
13472
+ * Enclave / Android Keystore / a non-extractable WebCrypto key). The private
13473
+ * key never travels. The hub signs the PUBLIC key into an X.509 leaf under a
13474
+ * dedicated device CA; the device later proves possession of the key by
13475
+ * signing a hub-issued nonce, and the hub answers with the same session a
13476
+ * password login opens.
13477
+ *
13478
+ * Everything on the wire is a small string (a PEM, a base64url signature):
13479
+ * D613 is about bulk bytes, and a certificate is ~600 bytes.
13480
+ */
13481
+ /** Signature algorithm of every device credential: ECDSA, curve P-256, SHA-256. */
13482
+ var DEVICE_CERT_SIGNATURE = "ecdsa-p256-sha256";
13483
+ /** First line of every signed message; a change of format bumps the version. */
13484
+ var DEVICE_SIGNATURE_MESSAGE_VERSION = "camstack-device-cert-v1";
13485
+ _enum([
13486
+ "login",
13487
+ "renew",
13488
+ "revoke"
13489
+ ]);
13490
+ var DevicePlatformSchema = _enum([
13491
+ "ios",
13492
+ "android",
13493
+ "web",
13494
+ "other"
13495
+ ]);
13496
+ var Base64UrlSchema = string().min(1).max(4096).regex(/^[A-Za-z0-9_-]+$/);
13497
+ var PemSchema = string().min(1).max(16384);
13498
+ /**
13499
+ * Why a device-certificate endpoint said no. Distinct from a transport / 5xx
13500
+ * failure: those carry no reason and mean "try again", never "the credential is
13501
+ * dead". The viewer switches on this exhaustively.
13502
+ */
13503
+ var DeviceRefusalReasonSchema = _enum([
13504
+ "revoked",
13505
+ "unknown-credential",
13506
+ "expired",
13507
+ "bad-signature",
13508
+ "nonce-invalid",
13509
+ "rate-limited",
13510
+ "invalid-certificate",
13511
+ "superseded",
13512
+ "user-gone",
13513
+ "unavailable",
13514
+ "code-invalid",
13515
+ "self-enrollment-disabled",
13516
+ "step-up-required",
13517
+ "bad-public-key"
13518
+ ]);
13519
+ var DeviceRefusalSchema = object({
13520
+ ok: literal(false),
13521
+ reason: DeviceRefusalReasonSchema,
13522
+ definitive: boolean(),
13523
+ retryAfterSeconds: number().optional()
13524
+ });
13525
+ object({
13526
+ code: string().min(1).max(256),
13527
+ /** SubjectPublicKeyInfo DER of the device's P-256 public key, base64url. */
13528
+ publicKeySpki: Base64UrlSchema,
13529
+ deviceName: string().min(1).max(80).optional(),
13530
+ platform: DevicePlatformSchema
13531
+ });
13532
+ discriminatedUnion("ok", [object({
13533
+ credentialId: string(),
13534
+ certPem: PemSchema,
13535
+ /** The device CA certificate the leaf chains to. */
13536
+ chainPem: PemSchema,
13537
+ notAfter: number(),
13538
+ user: object({
13539
+ id: string(),
13540
+ username: string()
13541
+ })
13542
+ }).extend({ ok: literal(true) }), DeviceRefusalSchema]);
13543
+ object({
13544
+ /** The single-use step-up proof (`auth.deviceEnrollProofFrom…`). */
13545
+ proof: string().min(1).max(512),
13546
+ publicKeySpki: Base64UrlSchema,
13547
+ deviceName: string().min(1).max(80),
13548
+ platform: DevicePlatformSchema
13549
+ });
13550
+ object({
13551
+ proof: string(),
13552
+ expiresAt: number()
13553
+ });
13554
+ discriminatedUnion("ok", [object({
13555
+ nonce: string(),
13556
+ /** The origin to put in the signed message. The app compares it to the hub it dialled. */
13557
+ origin: string(),
13558
+ expiresAt: number(),
13559
+ signature: literal(DEVICE_CERT_SIGNATURE)
13560
+ }).extend({ ok: literal(true) }), DeviceRefusalSchema]);
13561
+ object({
13562
+ certPem: PemSchema,
13563
+ nonce: string().min(1).max(256),
13564
+ /** ECDSA P-256 SHA-256 over {@link buildDeviceSignatureMessage}; raw r||s or DER, base64url. */
13565
+ signature: Base64UrlSchema
13566
+ });
13567
+ discriminatedUnion("ok", [object({
13568
+ credentialId: string(),
13569
+ certPem: PemSchema,
13570
+ chainPem: PemSchema,
13571
+ notAfter: number()
13572
+ }).extend({ ok: literal(true) }), DeviceRefusalSchema]);
13573
+ discriminatedUnion("ok", [object({
13574
+ ok: literal(true),
13575
+ credentialId: string(),
13576
+ sessionsEnded: number().int()
13577
+ }), DeviceRefusalSchema]);
13578
+ var DeviceCredentialStatusSchema = _enum([
13579
+ "active",
13580
+ "expired",
13581
+ "revoked"
13582
+ ]);
13583
+ var DeviceCredentialSchema = object({
13584
+ id: string(),
13585
+ userId: string(),
13586
+ username: string().nullable(),
13587
+ deviceName: string(),
13588
+ platform: DevicePlatformSchema,
13589
+ enrolledVia: _enum(["qr", "self"]),
13590
+ /** SHA-256 of the leaf certificate DER, colon-hex. */
13591
+ fingerprint: string(),
13592
+ issuedAt: number(),
13593
+ expiresAt: number(),
13594
+ lastUsedAt: number().nullable(),
13595
+ lastUsedFrom: string().nullable(),
13596
+ revokedAt: number().nullable(),
13597
+ /** `admin:<userId>` | `user:<userId>` | `device` | `user-deleted`. */
13598
+ revokedBy: string().nullable(),
13599
+ status: DeviceCredentialStatusSchema
13600
+ });
13601
+ var StartEnrollmentOutputSchema = object({
13602
+ /** Shown once; only its hash is kept. */
13603
+ code: string(),
13604
+ expiresAt: number(),
13605
+ /** `camstack://enroll?hub=…&code=…` — what the QR encodes. */
13606
+ enrollUrl: string(),
13607
+ /** The hub origin in the link, or `null` when the hub could not name one (the link then has no `hub`). */
13608
+ hubOrigin: string().nullable(),
13609
+ /** Every origin the apps may try (role `appConnections`). */
13610
+ hubOrigins: array(string())
13611
+ });
13612
+ object({
13613
+ kind: literal("device-certificate"),
13614
+ id: literal("device-certificate"),
13615
+ label: string(),
13616
+ stage: literal("primary"),
13617
+ /** tRPC paths under the hub's `auth` router, so a client names no literal. */
13618
+ challengePath: literal("auth.getDeviceChallenge"),
13619
+ revokePath: literal("auth.revokeOwnDeviceCertificate"),
13620
+ enrollSelfPath: literal("auth.enrollSelf"),
13621
+ loginPath: literal("auth.loginWithDeviceCertificate"),
13622
+ renewPath: literal("auth.renewDeviceCertificate"),
13623
+ signature: literal(DEVICE_CERT_SIGNATURE),
13624
+ messageVersion: literal(DEVICE_SIGNATURE_MESSAGE_VERSION),
13625
+ /** Which clients can execute it: a native app silently, a browser with a non-extractable WebCrypto key. */
13626
+ clients: array(_enum(["native", "web"])),
13627
+ /** The app executes it itself, silently (D858). */
13628
+ app: AppLoginPathSchema.nullable()
13629
+ });
13439
13630
  var ExpressionBindingSourceSchema = union([
13440
13631
  object({
13441
13632
  kind: literal("field").optional(),
@@ -13764,7 +13955,9 @@ var ConfigTabDeclarationSchema = object({
13764
13955
  var ConfigSectionWithValuesSchema = object({
13765
13956
  id: string(),
13766
13957
  title: string(),
13958
+ titleKey: string().optional(),
13767
13959
  description: string().optional(),
13960
+ descriptionKey: string().optional(),
13768
13961
  style: _enum(["card", "accordion"]).optional(),
13769
13962
  defaultCollapsed: boolean().optional(),
13770
13963
  columns: union([
@@ -16279,7 +16472,11 @@ var cameraStreamsCapability = {
16279
16472
  * See `RuntimeStateDurability`. Enforced by
16280
16473
  * `scripts/check-runtime-state-durability.ts`.
16281
16474
  */
16282
- durability: "session"
16475
+ durability: "session",
16476
+ /**
16477
+ * History (D850): none — `online` duplicates device-status.online (one authority); slot data is nested enum/string.
16478
+ */
16479
+ history: "none"
16283
16480
  };
16284
16481
  /** kebab-case cap name → camelCase router-map key. */
16285
16482
  function kebabToCamel(s) {
@@ -17122,7 +17319,345 @@ method(object({
17122
17319
  }), method(object({ refs: RefListSchema }), KeychainResolveResultSchema, { auth: "admin" }), method(object({ refs: RefListSchema }), object({ deleted: number().int() }), {
17123
17320
  kind: "mutation",
17124
17321
  auth: "admin"
17322
+ }), method(object({ deviceId: number().int() }), object({ refs: array(string()).readonly() }), {
17323
+ kind: "mutation",
17324
+ auth: "admin"
17125
17325
  }), method(object({}), array(KeychainSecretMetaSchema).readonly(), { auth: "admin" }), method(object({}), KeychainStateSchema, { auth: "admin" });
17326
+ /**
17327
+ * device-history — the ONE mechanism for numeric history (D850).
17328
+ *
17329
+ * A device value is recorded because its capability says so (the `history`
17330
+ * block of a `*.cap.ts`, captured hub-side from `DeviceStateChanged`); any
17331
+ * other series is DECLARED by the addon that produces it and fed with points
17332
+ * (`record`) or closed five-minute buckets (`recordBuckets`). Rollups 5m / 1h /
17333
+ * 1d are computed here and nowhere else. Storage is `history.db` (D851).
17334
+ *
17335
+ * Who the PRODUCER is: `declareSeries`, `record` and `recordBuckets` are owner
17336
+ * checked against the `callerAddonId` the transport stamps into a call that
17337
+ * crossed a process (never in an input schema, so a session cannot supply it).
17338
+ * A call with no stamp is refused `not-owner`. The methods are `admin` so a
17339
+ * non-admin session never reaches them; an addon's `ctx.api` call bypasses the
17340
+ * tier by design.
17341
+ */
17342
+ /** Whose history: a real device, or a cluster node (load, memory). */
17343
+ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17344
+ kind: literal("device"),
17345
+ deviceId: number().int()
17346
+ }), object({
17347
+ kind: literal("node"),
17348
+ nodeId: string().min(1)
17349
+ })]);
17350
+ var DeviceHistoryKindSchema = _enum([
17351
+ "gauge",
17352
+ "counter",
17353
+ "boolean"
17354
+ ]);
17355
+ var DeviceHistoryResolutionSchema = _enum([
17356
+ "raw",
17357
+ "5m",
17358
+ "1h",
17359
+ "1d"
17360
+ ]);
17361
+ /** Why a producer's point or bucket was not stored. Counted, never silent (D391). */
17362
+ var DeviceHistoryRefusalReasonSchema = _enum([
17363
+ "undeclared",
17364
+ "not-owner",
17365
+ "opted-out",
17366
+ "not-a-real-device",
17367
+ "rate",
17368
+ "ingest-mismatch",
17369
+ "out-of-range"
17370
+ ]);
17371
+ var RefusalSchema = object({
17372
+ key: string(),
17373
+ reason: DeviceHistoryRefusalReasonSchema,
17374
+ count: number().int()
17375
+ });
17376
+ var IngestResultSchema = object({
17377
+ accepted: number().int(),
17378
+ refused: array(RefusalSchema).readonly()
17379
+ });
17380
+ var SeriesInfoSchema = object({
17381
+ key: string(),
17382
+ scope: string(),
17383
+ kind: DeviceHistoryKindSchema,
17384
+ /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17385
+ unit: string().nullable(),
17386
+ displayName: string(),
17387
+ source: _enum(["cap", "addon"]),
17388
+ firstTs: number(),
17389
+ lastTs: number()
17390
+ });
17391
+ var QueryPointSchema = object({
17392
+ /** Raw: the point's time. Rollup: the bucket start. */
17393
+ t: number(),
17394
+ samples: number().int(),
17395
+ /** `sum / samples`. */
17396
+ mean: number().nullable(),
17397
+ /** Time-weighted mean (`tw_sum / tw_ms`); `null` for bucket-ingested series. For a boolean: the fraction of time true. */
17398
+ twMean: number().nullable(),
17399
+ min: number(),
17400
+ max: number(),
17401
+ /** `null` is unknown, never zero (D393). */
17402
+ last: number().nullable()
17403
+ });
17404
+ var QuerySeriesSchema = object({
17405
+ scope: string(),
17406
+ /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17407
+ before: object({
17408
+ t: number(),
17409
+ value: number().nullable()
17410
+ }).nullable(),
17411
+ points: array(QueryPointSchema).readonly()
17412
+ });
17413
+ /** The window part of a query, shared by the device and node forms. */
17414
+ var QueryWindowShape = {
17415
+ key: string(),
17416
+ scope: string().optional(),
17417
+ from: number(),
17418
+ to: number(),
17419
+ resolution: union([DeviceHistoryResolutionSchema, literal("auto")]).default("auto"),
17420
+ maxPoints: number().int().positive().max(5e3).default(1e3)
17421
+ };
17422
+ var QueryResultSchema = object({
17423
+ resolution: DeviceHistoryResolutionSchema,
17424
+ series: array(QuerySeriesSchema).readonly(),
17425
+ truncated: boolean()
17426
+ });
17427
+ var TierStatusSchema = object({
17428
+ tier: DeviceHistoryResolutionSchema,
17429
+ /** `null` until the first background count answered. */
17430
+ rows: number().int().nullable(),
17431
+ /** `rows` times a fixed per-row estimate — approximate, labelled so. */
17432
+ approxBytes: number().nullable(),
17433
+ countedAt: number().nullable()
17434
+ });
17435
+ /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17436
+ var DeviceHistoryStatusSchema = object({
17437
+ startedAt: number(),
17438
+ /** The store is declared, series loaded and the first reconcile has answered. */
17439
+ ready: boolean(),
17440
+ series: number().int(),
17441
+ metrics: number().int(),
17442
+ optedOutDevices: number().int(),
17443
+ tiers: array(TierStatusSchema).readonly(),
17444
+ capture: object({
17445
+ eventsSeen: number().int(),
17446
+ pointsEmitted: number().int(),
17447
+ pointsWritten: number().int(),
17448
+ pointsDropped: number().int(),
17449
+ bufferDepth: number().int(),
17450
+ trailingEmitted: number().int(),
17451
+ reconciledPoints: number().int(),
17452
+ reconcileRuns: number().int(),
17453
+ reconcileFailures: number().int(),
17454
+ lastReconcileAt: number().nullable(),
17455
+ lastFlushAt: number().nullable(),
17456
+ flushFailures: number().int(),
17457
+ skipped: record(string(), number().int())
17458
+ }),
17459
+ ingest: object({
17460
+ accepted: number().int(),
17461
+ refused: record(string(), number().int())
17462
+ }),
17463
+ rollup: object({
17464
+ last5mAt: number().nullable(),
17465
+ last1hAt: number().nullable(),
17466
+ last1dAt: number().nullable(),
17467
+ errors: number().int(),
17468
+ dirty5m: number().int(),
17469
+ dirty1h: number().int(),
17470
+ dirty1d: number().int()
17471
+ }),
17472
+ retention: object({
17473
+ lastRunAt: number().nullable(),
17474
+ deleted: record(string(), number().int()),
17475
+ purgedSeries: number().int()
17476
+ }),
17477
+ directory: object({
17478
+ devices: number().int(),
17479
+ lastRefreshAt: number().nullable()
17480
+ })
17481
+ });
17482
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17483
+ deviceId: number().int(),
17484
+ ...QueryWindowShape
17485
+ }), QueryResultSchema), method(object({
17486
+ nodeId: string().min(1),
17487
+ ...QueryWindowShape
17488
+ }), QueryResultSchema, { auth: "admin" }), method(object({
17489
+ name: string().regex(/^[a-z0-9-]+$/),
17490
+ subjectKind: _enum(["device", "node"]),
17491
+ kind: DeviceHistoryKindSchema,
17492
+ unit: string().optional(),
17493
+ displayName: string().min(1),
17494
+ ingest: _enum(["points", "buckets"])
17495
+ }), object({ key: string() }), {
17496
+ kind: "mutation",
17497
+ auth: "admin"
17498
+ }), method(object({ points: array(object({
17499
+ key: string(),
17500
+ subject: DeviceHistorySubjectSchema,
17501
+ scope: string().default(""),
17502
+ ts: number(),
17503
+ value: number()
17504
+ })).max(5e3) }), IngestResultSchema, {
17505
+ kind: "mutation",
17506
+ auth: "admin"
17507
+ }), method(object({ buckets: array(object({
17508
+ key: string(),
17509
+ subject: DeviceHistorySubjectSchema,
17510
+ scope: string().default(""),
17511
+ bucketStart: number(),
17512
+ samples: number().int().positive(),
17513
+ sum: number(),
17514
+ min: number(),
17515
+ max: number(),
17516
+ last: number().nullable(),
17517
+ lastTs: number().nullable()
17518
+ })).max(5e3) }), IngestResultSchema, {
17519
+ kind: "mutation",
17520
+ auth: "admin"
17521
+ }), method(object({ deviceId: number().int() }), object({ enabled: boolean() })), method(object({
17522
+ deviceId: number().int(),
17523
+ enabled: boolean()
17524
+ }), object({ enabled: boolean() }), {
17525
+ kind: "mutation",
17526
+ auth: "admin"
17527
+ }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17528
+ var DeviceCaStatusSchema = discriminatedUnion("state", [
17529
+ object({ state: literal("absent") }),
17530
+ object({
17531
+ state: literal("ready"),
17532
+ subject: string(),
17533
+ fingerprintSha256: string(),
17534
+ validTo: string()
17535
+ }),
17536
+ object({
17537
+ state: literal("unavailable"),
17538
+ reason: string()
17539
+ })
17540
+ ]);
17541
+ var DeviceCertificateSettingsSchema = object({ selfEnrollment: _enum(["allowed", "disabled"]) });
17542
+ method(object({
17543
+ userId: string().min(1).optional(),
17544
+ includeRevoked: boolean().default(false)
17545
+ }), array(DeviceCredentialSchema).readonly(), { auth: "admin" }), method(object({
17546
+ userId: string().min(1),
17547
+ deviceName: string().min(1).max(80)
17548
+ }), StartEnrollmentOutputSchema, {
17549
+ kind: "mutation",
17550
+ auth: "admin",
17551
+ caller: "required"
17552
+ }), method(object({ id: string().min(1) }), object({
17553
+ revoked: boolean(),
17554
+ sessionsEnded: number().int(),
17555
+ status: DeviceCredentialStatusSchema
17556
+ }), {
17557
+ kind: "mutation",
17558
+ auth: "admin",
17559
+ caller: "required"
17560
+ }), method(object({}), DeviceCertificateSettingsSchema, { auth: "admin" }), method(DeviceCertificateSettingsSchema, DeviceCertificateSettingsSchema, {
17561
+ kind: "mutation",
17562
+ auth: "admin"
17563
+ }), method(object({ id: string().min(1) }), object({ result: _enum([
17564
+ "deleted",
17565
+ "live",
17566
+ "unknown"
17567
+ ]) }), {
17568
+ kind: "mutation",
17569
+ auth: "admin",
17570
+ caller: "required"
17571
+ }), method(object({}), DeviceCaStatusSchema, { auth: "admin" }), method(object({
17572
+ id: string().min(1),
17573
+ deviceName: string().min(1).max(80)
17574
+ }), object({ renamed: boolean() }), {
17575
+ kind: "mutation",
17576
+ auth: "admin"
17577
+ });
17578
+ /**
17579
+ * `node-certificates` - what a node holds and the two renewals the hub drives
17580
+ * (D856): the node's MESH leaf (mutual TLS to the hub) and its HTTPS leaf (issued
17581
+ * from the hub's local CA so a device that trusts the hub root trusts the node).
17582
+ *
17583
+ * Provided by the AGENT RUNTIME (the synthetic `agent-runtime` addon id, like
17584
+ * `server-management`): the hub reaches it through the ordinary node-pinned
17585
+ * capability call - no new Moleculer action. The hub's own certificates are
17586
+ * handled in-process by the hub (`certificates` router), so this cap has no hub
17587
+ * provider.
17588
+ *
17589
+ * No private key ever crosses the mesh: the node generates its key pair, sends a
17590
+ * CSR, and the hub returns only the signed certificate.
17591
+ */
17592
+ var MeshLeafInfoSchema = object({
17593
+ cn: string(),
17594
+ serial: string(),
17595
+ fingerprintSha256: string(),
17596
+ notBefore: number(),
17597
+ notAfter: number()
17598
+ });
17599
+ var HttpsLeafInfoSchema = object({
17600
+ fingerprintSha256: string(),
17601
+ issuer: string(),
17602
+ sans: array(string()),
17603
+ notBefore: number(),
17604
+ notAfter: number()
17605
+ });
17606
+ var NodeHttpsStateSchema = discriminatedUnion("state", [object({
17607
+ state: literal("served"),
17608
+ leaf: HttpsLeafInfoSchema
17609
+ }), object({
17610
+ state: literal("not-issued"),
17611
+ reason: string()
17612
+ })]);
17613
+ method(object({}), object({
17614
+ nodeId: string(),
17615
+ mesh: MeshLeafInfoSchema.nullable(),
17616
+ https: NodeHttpsStateSchema
17617
+ }), { auth: "admin" }), method(object({}), object({ csrPem: string() }), {
17618
+ kind: "mutation",
17619
+ auth: "admin"
17620
+ }), method(object({
17621
+ certPem: string().min(1),
17622
+ caCertPem: string().min(1),
17623
+ confirmWithinMs: number().int().min(1e4).max(6e5)
17624
+ }), object({
17625
+ fingerprintSha256: string(),
17626
+ serial: string()
17627
+ }), {
17628
+ kind: "mutation",
17629
+ auth: "admin"
17630
+ }), method(object({ fingerprintSha256: string() }), object({ confirmed: boolean() }), {
17631
+ kind: "mutation",
17632
+ auth: "admin"
17633
+ }), method(object({}), object({ rolledBack: boolean() }), {
17634
+ kind: "mutation",
17635
+ auth: "admin"
17636
+ }), method(object({}), object({
17637
+ csrPem: string(),
17638
+ hostnames: array(string()),
17639
+ addresses: array(string()),
17640
+ /** SHA-256 of the hub local CA this node pinned at its first install; `null` before one. */
17641
+ pinnedCaFingerprintSha256: string().nullable()
17642
+ }), {
17643
+ kind: "mutation",
17644
+ auth: "admin"
17645
+ }), method(object({}), object({ ok: literal(true) }), {
17646
+ kind: "mutation",
17647
+ auth: "admin"
17648
+ }), method(object({
17649
+ certPem: string().min(1),
17650
+ caCertPem: string().min(1),
17651
+ /**
17652
+ * The hub signals that its local CA was rotated (D227) and this leaf chains to the NEW
17653
+ * one. Only the hub, over the authenticated mesh, can say so; a leaf with a different CA
17654
+ * and no signal is refused.
17655
+ */
17656
+ caRotation: boolean().optional()
17657
+ }), HttpsLeafInfoSchema, {
17658
+ kind: "mutation",
17659
+ auth: "admin"
17660
+ });
17126
17661
  var KeychainKeySourceSchema = object({
17127
17662
  kind: _enum([
17128
17663
  "config-file",
@@ -17597,6 +18132,10 @@ var deviceDiscoveryCapability = {
17597
18132
  * `scripts/check-runtime-state-durability.ts`.
17598
18133
  */
17599
18134
  durability: "session",
18135
+ /**
18136
+ * History (D850): none — inventory.
18137
+ */
18138
+ history: "none",
17600
18139
  methods: {
17601
18140
  /**
17602
18141
  * Snapshot of the current `discovered` list. Returns the
@@ -38297,6 +38836,42 @@ var DeviceRegisterPayloadSchema = object({
38297
38836
  * omits it and the keyword backstop applies. */
38298
38837
  secretConfigPaths: array(string()).optional()
38299
38838
  });
38839
+ /** One deleted device, kept by device-manager so an addon that missed the
38840
+ * deletion can still learn of it (D865). Written by the delete path ONLY. */
38841
+ var DeviceTombstoneSchema = object({
38842
+ deviceId: number().int().positive(),
38843
+ /** Epoch ms the device was deleted. */
38844
+ deletedAt: number(),
38845
+ /** The addon that owned the device when it was deleted. */
38846
+ providerAddonId: string()
38847
+ });
38848
+ /** How long a tombstone stays readable. Past it, a device that was deleted
38849
+ * and never cleaned is only reachable by the admin "clean data of deleted
38850
+ * devices" action. */
38851
+ var DEVICE_TOMBSTONE_RETENTION_MS = 2160 * 60 * 60 * 1e3;
38852
+ /** Data held for one device that device-manager no longer knows. */
38853
+ var OrphanDeviceDataSchema = object({
38854
+ deviceId: number().int().positive(),
38855
+ /** Rows/files per store (`<addonId>:<store>`). */
38856
+ stores: record(string(), number().int().nonnegative())
38857
+ });
38858
+ var CleanupDeletedDevicesResultSchema = object({
38859
+ /**
38860
+ * `skipped` — the absence check could not be trusted (a device-list read
38861
+ * failed or the two reads disagreed); nothing was listed or deleted.
38862
+ * `dry-run` — `devices` is what a confirmed run would delete.
38863
+ * `cleaned` — `devices` is what was deleted.
38864
+ */
38865
+ status: _enum([
38866
+ "skipped",
38867
+ "dry-run",
38868
+ "cleaned"
38869
+ ]),
38870
+ reason: string().nullable(),
38871
+ devices: array(OrphanDeviceDataSchema),
38872
+ /** Implementers that could not be asked (their stores are not in `devices`). */
38873
+ unreachable: array(string())
38874
+ });
38300
38875
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
38301
38876
  var DevicePersistConfigPayloadSchema = object({
38302
38877
  deviceId: number(),
@@ -38535,6 +39110,9 @@ method(object({
38535
39110
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
38536
39111
  kind: "mutation",
38537
39112
  auth: "admin"
39113
+ }), method(object({ sinceMs: number() }), array(DeviceTombstoneSchema).readonly(), { auth: "admin" }), method(object({ confirm: boolean() }), CleanupDeletedDevicesResultSchema, {
39114
+ kind: "mutation",
39115
+ auth: "admin"
38538
39116
  }), method(object({ integrationId: string() }), object({ removed: number() }), {
38539
39117
  kind: "mutation",
38540
39118
  auth: "admin"
@@ -39068,6 +39646,85 @@ var embeddingEncoderCapability = {
39068
39646
  }
39069
39647
  };
39070
39648
  /**
39649
+ * `device-removal-hook` — the reliable way an addon learns a device was DELETED,
39650
+ * so it can delete what it keeps for that device (D865).
39651
+ *
39652
+ * ## Why an event was not enough
39653
+ *
39654
+ * `DeviceUnregistered` is telemetry and may be dropped (D8, D11). An addon that
39655
+ * hung its per-device clean-up on it left durable garbage whenever the event was
39656
+ * lost, the addon was down, or it was restarting at that moment — footage,
39657
+ * analytics rows and settings of device 4483 outlived the device. Loss of this
39658
+ * signal corrupts durable state, so it travels by RPC with a recorded fact
39659
+ * behind it (D8: "if loss would corrupt durable state, use RPC plus a reconcile").
39660
+ *
39661
+ * ## The three pieces
39662
+ *
39663
+ * 1. device-manager records a TOMBSTONE per deleted device
39664
+ * (`deviceManager.listDeletedSince`). The tombstone is written by the delete
39665
+ * path only — a device that is unregistered, offline or whose provider is
39666
+ * restarting is NOT deleted and gets none.
39667
+ * 2. After a delete, device-manager calls `onDeviceRemoved` on EVERY provider of
39668
+ * this collection, one by one, with bounded retries, logged.
39669
+ * 3. An implementer that was down asks `deviceManager.listDeletedSince` at start
39670
+ * (and periodically) and runs its own `onDeviceRemoved` for each tombstone it
39671
+ * may have missed. Reconcile is driven by tombstones, never by "the device is
39672
+ * not in the current list": a failed or partial list read must not destroy data.
39673
+ *
39674
+ * ## Contract for an implementer
39675
+ *
39676
+ * - **Idempotent.** It is called again by a retry, by a reconcile and by the
39677
+ * admin cleanup of data that predates tombstones. A device with nothing left
39678
+ * answers zero counts.
39679
+ * - **One key per store** in `counts`, deleted rows/files per store, so the log
39680
+ * line and the admin dry run can say where the data was.
39681
+ * - **Training datasets are NOT device data** and are never deleted by a hook.
39682
+ * - **Per-device SETTINGS are not hooked.** Configuration lives in the standard
39683
+ * per-device store (`ctx.settings.*DeviceStore`), which device-manager clears
39684
+ * for every addon centrally at delete time. This hook is for device DATA
39685
+ * that is not settings: footage, event media, analytics rows, history.
39686
+ * - A provider that cannot tell is allowed to throw; the caller retries it.
39687
+ *
39688
+ * `listDeviceData` is the read side of the admin "Clean data of deleted devices"
39689
+ * action: which device ids this addon holds data for, and how much per store. It
39690
+ * never deletes. device-manager decides which of those ids are absent from the
39691
+ * fleet, from TWO consistent reads of the device list (D49).
39692
+ */
39693
+ /** What a hook is told about the deletion. */
39694
+ var DeviceRemovedInputSchema = object({
39695
+ deviceId: number().int().positive(),
39696
+ /** Epoch ms the device was deleted (the tombstone's `deletedAt`). */
39697
+ deletedAt: number(),
39698
+ /** The addon that owned the device, as device-manager last knew it. */
39699
+ providerAddonId: string()
39700
+ });
39701
+ /** Rows/files/refs deleted, per store this implementer owns. */
39702
+ var DeviceRemovedResultSchema = object({ counts: record(string(), number().int().nonnegative()) });
39703
+ /** One (store, device) pair an implementer holds data for. */
39704
+ var DeviceDataEntrySchema = object({
39705
+ store: string(),
39706
+ deviceId: number().int().positive(),
39707
+ /** Rows (or files) held for the device in the store. */
39708
+ count: number().int().nonnegative()
39709
+ });
39710
+ var deviceRemovalHookCapability = {
39711
+ name: "device-removal-hook",
39712
+ scope: "system",
39713
+ mode: "collection",
39714
+ internal: true,
39715
+ methods: {
39716
+ /** Delete everything this addon keeps for the deleted device. Idempotent. */
39717
+ onDeviceRemoved: method(DeviceRemovedInputSchema, DeviceRemovedResultSchema, {
39718
+ kind: "mutation",
39719
+ auth: "admin"
39720
+ }),
39721
+ /** Which devices this addon holds data for, per store. Reads only. */
39722
+ listDeviceData: method(_void(), array(DeviceDataEntrySchema).readonly(), { auth: "admin" })
39723
+ },
39724
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
39725
+ mount: { kind: "skip" }
39726
+ };
39727
+ /**
39071
39728
  * `failure-contribution` — the capability an addon reports its OWN losses
39072
39729
  * through, per camera, with the denominator attached. It stores nothing.
39073
39730
  *
@@ -40144,7 +40801,13 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
40144
40801
  * `beginExternalLink` offer exactly the redirect methods that set this,
40145
40802
  * whatever their id. Absent / false — a login button only.
40146
40803
  */
40147
- linkable: boolean().optional()
40804
+ linkable: boolean().optional(),
40805
+ /**
40806
+ * How a NATIVE app starts this method (D858): `{ kind: 'browser', startPath }`
40807
+ * when the route understands the app flow query (`app=1&code_challenge=…`),
40808
+ * `null`/absent when there is no app path - the app hides the method.
40809
+ */
40810
+ app: AppLoginPathSchema.nullable().optional()
40148
40811
  }),
40149
40812
  object({
40150
40813
  kind: literal("widget"),
@@ -40156,7 +40819,9 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
40156
40819
  bundle: string(),
40157
40820
  /** MF remote descriptor — `{ remoteName, exposedModule, componentKey }`. */
40158
40821
  remote: WidgetRemoteSchema,
40159
- stage: LoginStageEnum
40822
+ stage: LoginStageEnum,
40823
+ /** Widgets are web ceremonies: no native app path (D858). Absent reads as `null`. */
40824
+ app: AppLoginPathSchema.nullable().optional()
40160
40825
  }),
40161
40826
  object({
40162
40827
  kind: literal("passkey"),
@@ -40168,7 +40833,9 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
40168
40833
  /** Effective WebAuthn RP ID (`resolveRpID()`) — the shell gates visibility on it. */
40169
40834
  rpId: string(),
40170
40835
  /** Effective expected origin (`resolveOrigin()`), null when unconfigured. */
40171
- origin: string().nullable()
40836
+ origin: string().nullable(),
40837
+ /** Set by the hub for the primary arm; a second-factor passkey has no app path (D858). */
40838
+ app: AppLoginPathSchema.nullable().optional()
40172
40839
  })
40173
40840
  ]);
40174
40841
  method(_void(), array(LoginMethodContributionSchema).readonly());
@@ -40678,7 +41345,21 @@ var NetworkEndpointSchema = object({
40678
41345
  url: string(),
40679
41346
  hostname: string(),
40680
41347
  port: number(),
40681
- protocol: _enum(["http", "https"])
41348
+ protocol: _enum(["http", "https"]),
41349
+ /**
41350
+ * Whether this address survives a restart of its provider. `false` = it is
41351
+ * re-issued every time (a Quick tunnel's random `*.trycloudflare.com`); the
41352
+ * hub never selects such an address AUTOMATICALLY for a role (D860), though
41353
+ * it stays visible and an operator may still flag it. Absent = stable: every
41354
+ * provider except a Quick tunnel owns a name that does not change.
41355
+ */
41356
+ stable: boolean().optional()
41357
+ });
41358
+ object({
41359
+ url: string(),
41360
+ /** Mirrors {@link NetworkEndpointSchema} `stable`; absent = stable. */
41361
+ stable: boolean().optional(),
41362
+ updated: boolean().optional()
40682
41363
  });
40683
41364
  var NetworkAccessStatusSchema = object({
40684
41365
  connected: boolean(),
@@ -41806,6 +42487,10 @@ var alarmPanelCapability = {
41806
42487
  * `scripts/check-runtime-state-durability.ts`.
41807
42488
  */
41808
42489
  durability: "restored",
42490
+ /**
42491
+ * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
42492
+ */
42493
+ history: "none",
41809
42494
  /** Clock fields: written, but excluded from the compare that decides
41810
42495
  * whether persisting is worth a SQLite commit. */
41811
42496
  volatileStateFields: ["lastChangedAt"]
@@ -50220,7 +50905,11 @@ var zonesCapability = {
50220
50905
  * See `RuntimeStateDurability`. Enforced by
50221
50906
  * `scripts/check-runtime-state-durability.ts`.
50222
50907
  */
50223
- durability: "restored"
50908
+ durability: "restored",
50909
+ /**
50910
+ * History (D850): none — configuration arrays.
50911
+ */
50912
+ history: "none"
50224
50913
  };
50225
50914
  /**
50226
50915
  * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
@@ -52601,7 +53290,22 @@ var SsoBridgeClaimsSchema = object({
52601
53290
  * request to present the matching cookie — a login bridge is useless in
52602
53291
  * any other browser.
52603
53292
  */
52604
- browserBinding: string().optional()
53293
+ browserBinding: string().optional(),
53294
+ /**
53295
+ * The native app that started this sign-in (D858): its PKCE challenge,
53296
+ * `state`, purpose and allow-listed return URL, copied from the server-side
53297
+ * pending OIDC state. A bridge carrying it is finished ONLY at
53298
+ * `/api/auth/sso/finish-app` (which mints a handoff code, never a web
53299
+ * session); `/api/auth/sso/finish` refuses it.
53300
+ */
53301
+ app: object({
53302
+ codeChallenge: string(),
53303
+ state: string(),
53304
+ purpose: _enum(["new-session", "step-up"]),
53305
+ redirect: string(),
53306
+ /** The page language the app asked for (D858); the confirm page speaks it. */
53307
+ lang: _enum(["en", "it"]).optional()
53308
+ }).optional()
52605
53309
  });
52606
53310
  method(object({
52607
53311
  claims: SsoBridgeClaimsSchema,
@@ -53008,6 +53712,10 @@ var streamSignalsCapability = {
53008
53712
  * `scripts/check-runtime-state-durability.ts`.
53009
53713
  */
53010
53714
  durability: "session",
53715
+ /**
53716
+ * History (D850): none — array state.
53717
+ */
53718
+ history: "none",
53011
53719
  methods: {
53012
53720
  /**
53013
53721
  * What this device can emit. Empty is a valid and common answer — most
@@ -54870,7 +55578,12 @@ var SearchResultSchema = object({
54870
55578
  publishedAt: string(),
54871
55579
  author: string(),
54872
55580
  installed: boolean(),
54873
- installedVersion: string().optional()
55581
+ installedVersion: string().optional(),
55582
+ /**
55583
+ * Capability names the package's addons declare (from its published
55584
+ * manifest). `null` = the registry lookup failed — unknown, never `[]` (D393).
55585
+ */
55586
+ capabilities: array(string()).readonly().nullable()
54874
55587
  });
54875
55588
  var AutoUpdateSettingsSchema = object({
54876
55589
  channel: ChannelSchema,
@@ -55032,7 +55745,11 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
55032
55745
  }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
55033
55746
  kind: "mutation",
55034
55747
  auth: "admin"
55035
- }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
55748
+ }), method(object({
55749
+ query: string().optional(),
55750
+ /** Only packages whose addons declare this capability (unknown ones excluded). */
55751
+ capability: string().optional()
55752
+ }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
55036
55753
  name: string().min(1),
55037
55754
  version: string().optional(),
55038
55755
  nodeId: string().optional()
@@ -55168,6 +55885,36 @@ var airQualitySensorCapability = {
55168
55885
  * `scripts/check-runtime-state-durability.ts`.
55169
55886
  */
55170
55887
  durability: "restored",
55888
+ /**
55889
+ * History (D850): recorded series.
55890
+ */
55891
+ history: { fields: {
55892
+ co2Ppm: {
55893
+ kind: "gauge",
55894
+ unit: "ppm",
55895
+ deadband: 5
55896
+ },
55897
+ vocPpb: {
55898
+ kind: "gauge",
55899
+ unit: "ppb",
55900
+ deadband: 5
55901
+ },
55902
+ pm25: {
55903
+ kind: "gauge",
55904
+ unit: "ug/m3",
55905
+ deadband: 1
55906
+ },
55907
+ pm10: {
55908
+ kind: "gauge",
55909
+ unit: "ug/m3",
55910
+ deadband: 1
55911
+ },
55912
+ aqi: {
55913
+ kind: "gauge",
55914
+ unit: "count",
55915
+ deadband: 1
55916
+ }
55917
+ } },
55171
55918
  /** Clock fields: written, but excluded from the compare that decides
55172
55919
  * whether persisting is worth a SQLite commit. */
55173
55920
  volatileStateFields: ["lastFetchedAt"]
@@ -55210,6 +55957,15 @@ var ambientLightSensorCapability = {
55210
55957
  * `scripts/check-runtime-state-durability.ts`.
55211
55958
  */
55212
55959
  durability: "restored",
55960
+ /**
55961
+ * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
55962
+ */
55963
+ history: { fields: { lux: {
55964
+ kind: "gauge",
55965
+ unit: "lx",
55966
+ deadbandPct: 10,
55967
+ minIntervalMs: 6e4
55968
+ } } },
55213
55969
  /** Clock fields: written, but excluded from the compare that decides
55214
55970
  * whether persisting is worth a SQLite commit. */
55215
55971
  volatileStateFields: ["lastFetchedAt"]
@@ -55337,7 +56093,11 @@ var audioMetricsCapability = {
55337
56093
  * See `RuntimeStateDurability`. Enforced by
55338
56094
  * `scripts/check-runtime-state-durability.ts`.
55339
56095
  */
55340
- durability: "session"
56096
+ durability: "session",
56097
+ /**
56098
+ * History (D850): none — the level is the addon series `pipeline-analytics/audio-level` (producer `record`); the other numbers move every inference window and duplicate it.
56099
+ */
56100
+ history: "none"
55341
56101
  };
55342
56102
  /**
55343
56103
  * Automation-control cap. Models HA `automation.*` entities on
@@ -55406,7 +56166,11 @@ var automationControlCapability = {
55406
56166
  * See `RuntimeStateDurability`. Enforced by
55407
56167
  * `scripts/check-runtime-state-durability.ts`.
55408
56168
  */
55409
- durability: "session"
56169
+ durability: "session",
56170
+ /**
56171
+ * History (D850): none — configuration and transient run state.
56172
+ */
56173
+ history: "none"
55410
56174
  };
55411
56175
  /**
55412
56176
  * Battery status snapshot. Emitted by providers whose device is
@@ -55587,6 +56351,13 @@ onStatusChanged: { data: object({
55587
56351
  * `scripts/check-runtime-state-durability.ts`.
55588
56352
  */
55589
56353
  durability: "restored",
56354
+ /**
56355
+ * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
56356
+ */
56357
+ history: { fields: { percentage: {
56358
+ kind: "gauge",
56359
+ unit: "%"
56360
+ } } },
55590
56361
  /** Clock fields: written, but excluded from the compare that decides
55591
56362
  * whether persisting is worth a SQLite commit. */
55592
56363
  volatileStateFields: ["lastUpdated"]
@@ -55626,6 +56397,10 @@ var binaryCapability = {
55626
56397
  * `scripts/check-runtime-state-durability.ts`.
55627
56398
  */
55628
56399
  durability: "restored",
56400
+ /**
56401
+ * History (D850): recorded series.
56402
+ */
56403
+ history: { fields: { on: { kind: "boolean" } } },
55629
56404
  /** Clock fields: written, but excluded from the compare that decides
55630
56405
  * whether persisting is worth a SQLite commit. */
55631
56406
  volatileStateFields: ["lastChangedAt"]
@@ -55688,7 +56463,15 @@ onBrightnessChanged: { data: object({
55688
56463
  * See `RuntimeStateDurability`. Enforced by
55689
56464
  * `scripts/check-runtime-state-durability.ts`.
55690
56465
  */
55691
- durability: "session"
56466
+ durability: "session",
56467
+ /**
56468
+ * History (D850): recorded series. Actuator tier: level keeps every change.
56469
+ */
56470
+ history: { fields: { percentage: {
56471
+ kind: "gauge",
56472
+ unit: "%",
56473
+ minIntervalMs: 0
56474
+ } } }
55692
56475
  };
55693
56476
  DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
55694
56477
  kind: "mutation",
@@ -56049,6 +56832,10 @@ var carbonMonoxideCapability = {
56049
56832
  * `scripts/check-runtime-state-durability.ts`.
56050
56833
  */
56051
56834
  durability: "restored",
56835
+ /**
56836
+ * History (D850): recorded series.
56837
+ */
56838
+ history: { fields: { detected: { kind: "boolean" } } },
56052
56839
  /** Clock fields: written, but excluded from the compare that decides
56053
56840
  * whether persisting is worth a SQLite commit. */
56054
56841
  volatileStateFields: ["lastChangedAt"]
@@ -56218,7 +57005,37 @@ var climateControlCapability = {
56218
57005
  * See `RuntimeStateDurability`. Enforced by
56219
57006
  * `scripts/check-runtime-state-durability.ts`.
56220
57007
  */
56221
- durability: "session"
57008
+ durability: "session",
57009
+ /**
57010
+ * History (D850): recorded series. Celsius by contract; setpoints keep every change (`minIntervalMs: 0`).
57011
+ */
57012
+ history: { fields: {
57013
+ currentTemp: {
57014
+ kind: "gauge",
57015
+ unit: "°C",
57016
+ deadband: .1
57017
+ },
57018
+ currentHumidity: {
57019
+ kind: "gauge",
57020
+ unit: "%",
57021
+ deadband: .5
57022
+ },
57023
+ target: {
57024
+ kind: "gauge",
57025
+ unit: "°C",
57026
+ minIntervalMs: 0
57027
+ },
57028
+ targetHigh: {
57029
+ kind: "gauge",
57030
+ unit: "°C",
57031
+ minIntervalMs: 0
57032
+ },
57033
+ targetLow: {
57034
+ kind: "gauge",
57035
+ unit: "°C",
57036
+ minIntervalMs: 0
57037
+ }
57038
+ } }
56222
57039
  };
56223
57040
  /**
56224
57041
  * Color-light cap. Coexists with `switch` (on/off) and `brightness`
@@ -56335,7 +57152,11 @@ onColorChanged: { data: object({
56335
57152
  * See `RuntimeStateDurability`. Enforced by
56336
57153
  * `scripts/check-runtime-state-durability.ts`.
56337
57154
  */
56338
- durability: "session"
57155
+ durability: "session",
57156
+ /**
57157
+ * History (D850): none — nested and cosmetic.
57158
+ */
57159
+ history: "none"
56339
57160
  };
56340
57161
  var ConnectionTestOutcomeSchema = discriminatedUnion("outcome", [
56341
57162
  object({
@@ -56401,6 +57222,10 @@ var connectivityCapability = {
56401
57222
  * `scripts/check-runtime-state-durability.ts`.
56402
57223
  */
56403
57224
  durability: "restored",
57225
+ /**
57226
+ * History (D850): none — duplicates device-status.online (one authority for availability).
57227
+ */
57228
+ history: "none",
56404
57229
  /** Clock fields: written, but excluded from the compare that decides
56405
57230
  * whether persisting is worth a SQLite commit. */
56406
57231
  volatileStateFields: ["lastChangedAt"]
@@ -56525,6 +57350,10 @@ reset: method(object({
56525
57350
  * `scripts/check-runtime-state-durability.ts`.
56526
57351
  */
56527
57352
  durability: "restored",
57353
+ /**
57354
+ * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
57355
+ */
57356
+ history: "none",
56528
57357
  /** Clocks, not content: a re-read that changed no item costs no commit. */
56529
57358
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
56530
57359
  };
@@ -56565,6 +57394,10 @@ var contactCapability = {
56565
57394
  * `scripts/check-runtime-state-durability.ts`.
56566
57395
  */
56567
57396
  durability: "restored",
57397
+ /**
57398
+ * History (D850): recorded series.
57399
+ */
57400
+ history: { fields: { entryOpen: { kind: "boolean" } } },
56568
57401
  /** Clock fields: written, but excluded from the compare that decides
56569
57402
  * whether persisting is worth a SQLite commit. */
56570
57403
  volatileStateFields: ["lastChangedAt"]
@@ -56680,7 +57513,11 @@ var controlCapability = {
56680
57513
  * See `RuntimeStateDurability`. Enforced by
56681
57514
  * `scripts/check-runtime-state-durability.ts`.
56682
57515
  */
56683
- durability: "session"
57516
+ durability: "session",
57517
+ /**
57518
+ * History (D850): none — `value` is a number/string union; configuration entity.
57519
+ */
57520
+ history: "none"
56684
57521
  };
56685
57522
  /**
56686
57523
  * Window covering / blinds / garage door / valve cap. Models HA
@@ -56771,6 +57608,14 @@ var coverCapability = {
56771
57608
  * `scripts/check-runtime-state-durability.ts`.
56772
57609
  */
56773
57610
  durability: "restored",
57611
+ /**
57612
+ * History (D850): recorded series. Actuator tier: position keeps every tick of a movement.
57613
+ */
57614
+ history: { fields: { position: {
57615
+ kind: "gauge",
57616
+ unit: "%",
57617
+ minIntervalMs: 0
57618
+ } } },
56774
57619
  /** Clock fields: written, but excluded from the compare that decides
56775
57620
  * whether persisting is worth a SQLite commit. */
56776
57621
  volatileStateFields: ["lastChangedAt"]
@@ -56875,6 +57720,10 @@ var dayNightCapability = {
56875
57720
  * `scripts/check-runtime-state-durability.ts`.
56876
57721
  */
56877
57722
  durability: "restored",
57723
+ /**
57724
+ * History (D850): none — firmware configuration, not a measurement.
57725
+ */
57726
+ history: "none",
56878
57727
  /** Clock fields: written, but excluded from the compare that decides
56879
57728
  * whether persisting is worth a SQLite commit. */
56880
57729
  volatileStateFields: ["lastFetchedAt"]
@@ -56932,6 +57781,10 @@ onStatusChanged: { data: object({
56932
57781
  * `scripts/check-runtime-state-durability.ts`.
56933
57782
  */
56934
57783
  durability: "restored",
57784
+ /**
57785
+ * History (D850): recorded series. The ONE availability series.
57786
+ */
57787
+ history: { fields: { online: { kind: "boolean" } } },
56935
57788
  /** Clock fields: written, but excluded from the compare that decides
56936
57789
  * whether persisting is worth a SQLite commit. */
56937
57790
  volatileStateFields: ["lastChangedAt"]
@@ -56998,7 +57851,11 @@ onPressed: {
56998
57851
  * See `RuntimeStateDurability`. Enforced by
56999
57852
  * `scripts/check-runtime-state-durability.ts`.
57000
57853
  */
57001
- durability: "restored"
57854
+ durability: "restored",
57855
+ /**
57856
+ * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
57857
+ */
57858
+ history: "none"
57002
57859
  };
57003
57860
  /**
57004
57861
  * Enum-state sensor — a string value picked from a finite option set.
@@ -57046,6 +57903,10 @@ var enumSensorCapability = {
57046
57903
  * `scripts/check-runtime-state-durability.ts`.
57047
57904
  */
57048
57905
  durability: "restored",
57906
+ /**
57907
+ * History (D850): none — text/enum state has no history (non-goal).
57908
+ */
57909
+ history: "none",
57049
57910
  /** Clock fields: written, but excluded from the compare that decides
57050
57911
  * whether persisting is worth a SQLite commit. */
57051
57912
  volatileStateFields: ["lastFetchedAt"]
@@ -57091,7 +57952,11 @@ var eventEmitterCapability = {
57091
57952
  * See `RuntimeStateDurability`. Enforced by
57092
57953
  * `scripts/check-runtime-state-durability.ts`.
57093
57954
  */
57094
- durability: "session"
57955
+ durability: "session",
57956
+ /**
57957
+ * History (D850): none — `eventCountSinceStart` resets with the addon; events live in ledgers.
57958
+ */
57959
+ history: "none"
57095
57960
  };
57096
57961
  var IdentitySchema = object({
57097
57962
  id: string(),
@@ -57587,7 +58452,18 @@ var fanControlCapability = {
57587
58452
  * See `RuntimeStateDurability`. Enforced by
57588
58453
  * `scripts/check-runtime-state-durability.ts`.
57589
58454
  */
57590
- durability: "session"
58455
+ durability: "session",
58456
+ /**
58457
+ * History (D850): recorded series. Actuator tier: speed keeps every change.
58458
+ */
58459
+ history: { fields: {
58460
+ percentage: {
58461
+ kind: "gauge",
58462
+ unit: "%",
58463
+ minIntervalMs: 0
58464
+ },
58465
+ oscillating: { kind: "boolean" }
58466
+ } }
57591
58467
  };
57592
58468
  /**
57593
58469
  * Per-device feature/identity probe slice. Holds the runtime-resolved
@@ -57670,7 +58546,11 @@ onProbeChanged: { data: object({
57670
58546
  * See `RuntimeStateDurability`. Enforced by
57671
58547
  * `scripts/check-runtime-state-durability.ts`.
57672
58548
  */
57673
- durability: "session"
58549
+ durability: "session",
58550
+ /**
58551
+ * History (D850): none — static identity and capability probe.
58552
+ */
58553
+ history: "none"
57674
58554
  };
57675
58555
  /**
57676
58556
  * Water leak / moisture sensor. Boolean "is liquid currently
@@ -57705,6 +58585,10 @@ var floodCapability = {
57705
58585
  * `scripts/check-runtime-state-durability.ts`.
57706
58586
  */
57707
58587
  durability: "restored",
58588
+ /**
58589
+ * History (D850): recorded series.
58590
+ */
58591
+ history: { fields: { flooded: { kind: "boolean" } } },
57708
58592
  /** Clock fields: written, but excluded from the compare that decides
57709
58593
  * whether persisting is worth a SQLite commit. */
57710
58594
  volatileStateFields: ["lastChangedAt"]
@@ -57738,6 +58622,10 @@ var gasCapability = {
57738
58622
  * `scripts/check-runtime-state-durability.ts`.
57739
58623
  */
57740
58624
  durability: "restored",
58625
+ /**
58626
+ * History (D850): recorded series.
58627
+ */
58628
+ history: { fields: { detected: { kind: "boolean" } } },
57741
58629
  /** Clock fields: written, but excluded from the compare that decides
57742
58630
  * whether persisting is worth a SQLite commit. */
57743
58631
  volatileStateFields: ["lastChangedAt"]
@@ -57823,7 +58711,18 @@ var humidifierCapability = {
57823
58711
  * See `RuntimeStateDurability`. Enforced by
57824
58712
  * `scripts/check-runtime-state-durability.ts`.
57825
58713
  */
57826
- durability: "session"
58714
+ durability: "session",
58715
+ /**
58716
+ * History (D850): recorded series.
58717
+ */
58718
+ history: { fields: {
58719
+ currentHumidity: {
58720
+ kind: "gauge",
58721
+ unit: "%",
58722
+ deadband: .5
58723
+ },
58724
+ on: { kind: "boolean" }
58725
+ } }
57827
58726
  };
57828
58727
  /**
57829
58728
  * Single-metric humidity reading. Drives Home Assistant `sensor`
@@ -57867,6 +58766,14 @@ var humiditySensorCapability = {
57867
58766
  * `scripts/check-runtime-state-durability.ts`.
57868
58767
  */
57869
58768
  durability: "restored",
58769
+ /**
58770
+ * History (D850): recorded series.
58771
+ */
58772
+ history: { fields: { percent: {
58773
+ kind: "gauge",
58774
+ unit: "%",
58775
+ deadband: .5
58776
+ } } },
57870
58777
  /** Clock fields: written, but excluded from the compare that decides
57871
58778
  * whether persisting is worth a SQLite commit. */
57872
58779
  volatileStateFields: ["lastFetchedAt"]
@@ -57914,7 +58821,11 @@ var imageCapability = {
57914
58821
  * See `RuntimeStateDurability`. Enforced by
57915
58822
  * `scripts/check-runtime-state-durability.ts`.
57916
58823
  */
57917
- durability: "session"
58824
+ durability: "session",
58825
+ /**
58826
+ * History (D850): none — not numeric.
58827
+ */
58828
+ history: "none"
57918
58829
  };
57919
58830
  /**
57920
58831
  * Vendor-neutral image / picture-adjustment cap — the per-camera config
@@ -58071,6 +58982,10 @@ var imageSettingsCapability = {
58071
58982
  * `scripts/check-runtime-state-durability.ts`.
58072
58983
  */
58073
58984
  durability: "restored",
58985
+ /**
58986
+ * History (D850): none — camera image configuration (operator intent), not a trend.
58987
+ */
58988
+ history: "none",
58074
58989
  /** Clock fields: written, but excluded from the compare that decides
58075
58990
  * whether persisting is worth a SQLite commit. */
58076
58991
  volatileStateFields: ["lastFetchedAt"]
@@ -58456,7 +59371,11 @@ var intercomCapability = {
58456
59371
  * See `RuntimeStateDurability`. Enforced by
58457
59372
  * `scripts/check-runtime-state-durability.ts`.
58458
59373
  */
58459
- durability: "session"
59374
+ durability: "session",
59375
+ /**
59376
+ * History (D850): none — talk sessions are a ledger concern, not a trend.
59377
+ */
59378
+ history: "none"
58460
59379
  };
58461
59380
  /**
58462
59381
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
@@ -58537,7 +59456,15 @@ var lawnMowerControlCapability = {
58537
59456
  * See `RuntimeStateDurability`. Enforced by
58538
59457
  * `scripts/check-runtime-state-durability.ts`.
58539
59458
  */
58540
- durability: "session"
59459
+ durability: "session",
59460
+ /**
59461
+ * History (D850): recorded series.
59462
+ */
59463
+ history: { fields: { batteryLevel: {
59464
+ kind: "gauge",
59465
+ unit: "%",
59466
+ deadband: 2
59467
+ } } }
58541
59468
  };
58542
59469
  /**
58543
59470
  * local-network — hub-only singleton.
@@ -58664,7 +59591,13 @@ var ConnectionEndpointSchema = object({
58664
59591
  * calls so the client can sort even if the cap returns a new
58665
59592
  * ordering between polls.
58666
59593
  */
58667
- priority: number()
59594
+ priority: number(),
59595
+ /**
59596
+ * `false` = the address changes on its own (a Quick tunnel, re-issued on
59597
+ * every respawn). Automatic role resolution skips it (D860); an explicit
59598
+ * operator flag still honours it. Absent = stable.
59599
+ */
59600
+ stable: boolean().optional()
58668
59601
  });
58669
59602
  /**
58670
59603
  * Where the advertised local port came from. Ordered most → least
@@ -58965,6 +59898,10 @@ var lockControlCapability = {
58965
59898
  * `scripts/check-runtime-state-durability.ts`.
58966
59899
  */
58967
59900
  durability: "restored",
59901
+ /**
59902
+ * History (D850): none — enum state; lock events belong in the events ledger.
59903
+ */
59904
+ history: "none",
58968
59905
  /** Clock fields: written, but excluded from the compare that decides
58969
59906
  * whether persisting is worth a SQLite commit. */
58970
59907
  volatileStateFields: ["lastChangedAt"]
@@ -59136,7 +60073,11 @@ var mediaPlayerCapability = {
59136
60073
  * See `RuntimeStateDurability`. Enforced by
59137
60074
  * `scripts/check-runtime-state-durability.ts`.
59138
60075
  */
59139
- durability: "session"
60076
+ durability: "session",
60077
+ /**
60078
+ * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
60079
+ */
60080
+ history: "none"
59140
60081
  };
59141
60082
  /**
59142
60083
  * mesh-network — collection cap for mesh-VPN providers.
@@ -59470,7 +60411,14 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
59470
60411
  * See `RuntimeStateDurability`. Enforced by
59471
60412
  * `scripts/check-runtime-state-durability.ts`.
59472
60413
  */
59473
- durability: "session"
60414
+ durability: "session",
60415
+ /**
60416
+ * History (D850): recorded series. A PIR sensor is a series; a camera is not (its motion is an addon series and a ledger).
60417
+ */
60418
+ history: { fields: { detected: {
60419
+ kind: "boolean",
60420
+ excludeDeviceTypes: [DeviceType.Camera]
60421
+ } } }
59474
60422
  };
59475
60423
  /**
59476
60424
  * Motion-trigger toggle for accessory devices.
@@ -59542,7 +60490,11 @@ var motionTriggerCapability = {
59542
60490
  * See `RuntimeStateDurability`. Enforced by
59543
60491
  * `scripts/check-runtime-state-durability.ts`.
59544
60492
  */
59545
- durability: "session"
60493
+ durability: "session",
60494
+ /**
60495
+ * History (D850): none — configuration switch.
60496
+ */
60497
+ history: "none"
59546
60498
  };
59547
60499
  /**
59548
60500
  * Motion-zones share the same MaskShape vocabulary as privacy-mask — the
@@ -59617,6 +60569,10 @@ var motionZonesCapability = {
59617
60569
  * `scripts/check-runtime-state-durability.ts`.
59618
60570
  */
59619
60571
  durability: "restored",
60572
+ /**
60573
+ * History (D850): none — configuration.
60574
+ */
60575
+ history: "none",
59620
60576
  /** Clock fields: written, but excluded from the compare that decides
59621
60577
  * whether persisting is worth a SQLite commit. */
59622
60578
  volatileStateFields: ["lastFetchedAt"]
@@ -59746,6 +60702,10 @@ var nativeObjectDetectionCapability = {
59746
60702
  * `scripts/check-runtime-state-durability.ts`.
59747
60703
  */
59748
60704
  durability: "restored",
60705
+ /**
60706
+ * History (D850): none — event-like and nested per class; detections live in the objects ledger.
60707
+ */
60708
+ history: "none",
59749
60709
  /** Clock fields: written, but excluded from the compare that decides
59750
60710
  * whether persisting is worth a SQLite commit. */
59751
60711
  volatileStateFields: ["lastFetchedAt"]
@@ -60029,7 +60989,11 @@ var navigationCapability = {
60029
60989
  * See `RuntimeStateDurability`. Enforced by
60030
60990
  * `scripts/check-runtime-state-durability.ts`.
60031
60991
  */
60032
- durability: "session"
60992
+ durability: "session",
60993
+ /**
60994
+ * History (D850): none — control state of a robotic camera, configuration-like.
60995
+ */
60996
+ history: "none"
60033
60997
  };
60034
60998
  /**
60035
60999
  * Network-link snapshot. Same shape for every provider (a Reolink wifi
@@ -60109,6 +61073,23 @@ onStatusChanged: { data: object({
60109
61073
  * `scripts/check-runtime-state-durability.ts`.
60110
61074
  */
60111
61075
  durability: "restored",
61076
+ /**
61077
+ * History (D850): recorded series.
61078
+ */
61079
+ history: { fields: {
61080
+ signalPercent: {
61081
+ kind: "gauge",
61082
+ unit: "%",
61083
+ deadband: 3,
61084
+ minIntervalMs: 6e4
61085
+ },
61086
+ rssiDbm: {
61087
+ kind: "gauge",
61088
+ unit: "dBm",
61089
+ deadband: 2,
61090
+ minIntervalMs: 6e4
61091
+ }
61092
+ } },
60112
61093
  /** Clock fields: written, but excluded from the compare that decides
60113
61094
  * whether persisting is worth a SQLite commit. */
60114
61095
  volatileStateFields: ["lastUpdated"]
@@ -60497,7 +61478,11 @@ onSent: { data: object({
60497
61478
  * See `RuntimeStateDurability`. Enforced by
60498
61479
  * `scripts/check-runtime-state-durability.ts`.
60499
61480
  */
60500
- durability: "session"
61481
+ durability: "session",
61482
+ /**
61483
+ * History (D850): none — `queueDepth` is outbox operational state, not a device trend.
61484
+ */
61485
+ history: "none"
60501
61486
  };
60502
61487
  /**
60503
61488
  * Generic numeric sensor — last-resort fallback when no typed numeric
@@ -60548,6 +61533,14 @@ var numericSensorCapability = {
60548
61533
  * `scripts/check-runtime-state-durability.ts`.
60549
61534
  */
60550
61535
  durability: "restored",
61536
+ /**
61537
+ * History (D850): recorded series. The unit is per device, read from the sibling `unit` field.
61538
+ */
61539
+ history: { fields: { value: {
61540
+ kind: "gauge",
61541
+ unitFrom: "unit",
61542
+ minIntervalMs: 3e4
61543
+ } } },
60551
61544
  /** Clock fields: written, but excluded from the compare that decides
60552
61545
  * whether persisting is worth a SQLite commit. */
60553
61546
  volatileStateFields: ["lastFetchedAt"]
@@ -60978,7 +61971,24 @@ var petFeederCapability = {
60978
61971
  * See `RuntimeStateDurability`. Enforced by
60979
61972
  * `scripts/check-runtime-state-durability.ts`.
60980
61973
  */
60981
- durability: "session"
61974
+ durability: "session",
61975
+ /**
61976
+ * History (D850): recorded series.
61977
+ */
61978
+ history: { fields: {
61979
+ foodLevel: { kind: "gauge" },
61980
+ food1: { kind: "gauge" },
61981
+ food2: { kind: "gauge" },
61982
+ batteryPower: {
61983
+ kind: "gauge",
61984
+ unit: "%",
61985
+ deadband: 2
61986
+ },
61987
+ desiccantLeftDays: {
61988
+ kind: "gauge",
61989
+ unit: "days"
61990
+ }
61991
+ } }
60982
61992
  };
60983
61993
  var VehicleSchema = object({
60984
61994
  id: string(),
@@ -61390,6 +62400,47 @@ var powerMeterCapability = {
61390
62400
  * `scripts/check-runtime-state-durability.ts`.
61391
62401
  */
61392
62402
  durability: "restored",
62403
+ /**
62404
+ * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
62405
+ */
62406
+ history: { fields: {
62407
+ watts: {
62408
+ kind: "gauge",
62409
+ unit: "W",
62410
+ deadband: 1,
62411
+ minIntervalMs: 3e4
62412
+ },
62413
+ kwhTotal: {
62414
+ kind: "counter",
62415
+ unit: "kWh",
62416
+ deadband: .01,
62417
+ minIntervalMs: 6e4
62418
+ },
62419
+ volts: {
62420
+ kind: "gauge",
62421
+ unit: "V",
62422
+ deadband: 1,
62423
+ minIntervalMs: 3e4
62424
+ },
62425
+ amps: {
62426
+ kind: "gauge",
62427
+ unit: "A",
62428
+ deadband: .05,
62429
+ minIntervalMs: 3e4
62430
+ },
62431
+ va: {
62432
+ kind: "gauge",
62433
+ unit: "VA",
62434
+ deadband: 1,
62435
+ minIntervalMs: 3e4
62436
+ },
62437
+ powerFactor: {
62438
+ kind: "gauge",
62439
+ unit: "ratio",
62440
+ deadband: .01,
62441
+ minIntervalMs: 6e4
62442
+ }
62443
+ } },
61393
62444
  /** Clock fields: written, but excluded from the compare that decides
61394
62445
  * whether persisting is worth a SQLite commit. */
61395
62446
  volatileStateFields: ["lastFetchedAt"]
@@ -61457,6 +62508,14 @@ var presenceCapability = {
61457
62508
  * `scripts/check-runtime-state-durability.ts`.
61458
62509
  */
61459
62510
  durability: "restored",
62511
+ /**
62512
+ * History (D850): recorded series.
62513
+ */
62514
+ history: { fields: { batteryPercent: {
62515
+ kind: "gauge",
62516
+ unit: "%",
62517
+ deadband: 1
62518
+ } } },
61460
62519
  /** Clock fields: written, but excluded from the compare that decides
61461
62520
  * whether persisting is worth a SQLite commit. */
61462
62521
  volatileStateFields: ["lastChangedAt"]
@@ -61503,6 +62562,14 @@ var pressureSensorCapability = {
61503
62562
  * `scripts/check-runtime-state-durability.ts`.
61504
62563
  */
61505
62564
  durability: "restored",
62565
+ /**
62566
+ * History (D850): recorded series.
62567
+ */
62568
+ history: { fields: { hpa: {
62569
+ kind: "gauge",
62570
+ unit: "hPa",
62571
+ deadband: .1
62572
+ } } },
61506
62573
  /** Clock fields: written, but excluded from the compare that decides
61507
62574
  * whether persisting is worth a SQLite commit. */
61508
62575
  volatileStateFields: ["lastFetchedAt"]
@@ -61662,6 +62729,10 @@ var privacyMaskCapability = {
61662
62729
  * `scripts/check-runtime-state-durability.ts`.
61663
62730
  */
61664
62731
  durability: "restored",
62732
+ /**
62733
+ * History (D850): none — configuration.
62734
+ */
62735
+ history: "none",
61665
62736
  /** Clock fields: written, but excluded from the compare that decides
61666
62737
  * whether persisting is worth a SQLite commit. */
61667
62738
  volatileStateFields: ["lastFetchedAt"]
@@ -62023,7 +63094,11 @@ var ptzAutotrackCapability = {
62023
63094
  * See `RuntimeStateDurability`. Enforced by
62024
63095
  * `scripts/check-runtime-state-durability.ts`.
62025
63096
  */
62026
- durability: "session"
63097
+ durability: "session",
63098
+ /**
63099
+ * History (D850): none — configuration and capability.
63100
+ */
63101
+ history: "none"
62027
63102
  };
62028
63103
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
62029
63104
  kind: "mutation",
@@ -63481,6 +64556,10 @@ var recordingOnboardCapability = {
63481
64556
  * `scripts/check-runtime-state-durability.ts`.
63482
64557
  */
63483
64558
  durability: "restored",
64559
+ /**
64560
+ * History (D850): none — SD-card configuration and window inventory; arrays.
64561
+ */
64562
+ history: "none",
63484
64563
  /** Clock fields: written, but excluded from the compare that decides
63485
64564
  * whether persisting is worth a SQLite commit. */
63486
64565
  volatileStateFields: ["lastFetchedAt"]
@@ -63554,7 +64633,11 @@ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) }
63554
64633
  * See `RuntimeStateDurability`. Enforced by
63555
64634
  * `scripts/check-runtime-state-durability.ts`.
63556
64635
  */
63557
- durability: "session"
64636
+ durability: "session",
64637
+ /**
64638
+ * History (D850): none — recording intent is already in the recordings ledger.
64639
+ */
64640
+ history: "none"
63558
64641
  };
63559
64642
  /**
63560
64643
  * scene-monitor — device-scoped reference-region state cap. An operator marks
@@ -63945,7 +65028,11 @@ var sceneMonitorCapability = {
63945
65028
  * See `RuntimeStateDurability`. Enforced by
63946
65029
  * `scripts/check-runtime-state-durability.ts`.
63947
65030
  */
63948
- durability: "session"
65031
+ durability: "session",
65032
+ /**
65033
+ * History (D850): none — nested configuration.
65034
+ */
65035
+ history: "none"
63949
65036
  };
63950
65037
  /**
63951
65038
  * Per-stage gating mode applied to the zones a rule references.
@@ -64096,7 +65183,11 @@ var scriptRunnerCapability = {
64096
65183
  * See `RuntimeStateDurability`. Enforced by
64097
65184
  * `scripts/check-runtime-state-durability.ts`.
64098
65185
  */
64099
- durability: "session"
65186
+ durability: "session",
65187
+ /**
65188
+ * History (D850): none — transient; run results belong in a ledger.
65189
+ */
65190
+ history: "none"
64100
65191
  };
64101
65192
  /**
64102
65193
  * Smoke alarm sensor — boolean "is smoke currently detected" with
@@ -64131,6 +65222,10 @@ var smokeCapability = {
64131
65222
  * `scripts/check-runtime-state-durability.ts`.
64132
65223
  */
64133
65224
  durability: "restored",
65225
+ /**
65226
+ * History (D850): recorded series.
65227
+ */
65228
+ history: { fields: { detected: { kind: "boolean" } } },
64134
65229
  /** Clock fields: written, but excluded from the compare that decides
64135
65230
  * whether persisting is worth a SQLite commit. */
64136
65231
  volatileStateFields: ["lastChangedAt"]
@@ -64230,6 +65325,10 @@ var streamCatalogCapability = {
64230
65325
  * `scripts/check-runtime-state-durability.ts`.
64231
65326
  */
64232
65327
  durability: "restored",
65328
+ /**
65329
+ * History (D850): none — stream inventory.
65330
+ */
65331
+ history: "none",
64233
65332
  /** Clock field: written, but excluded from the compare that decides whether
64234
65333
  * persisting is worth a SQLite commit — the descriptors are the value. */
64235
65334
  volatileStateFields: ["lastFetchedAt"]
@@ -64379,6 +65478,10 @@ var streamParamsCapability = {
64379
65478
  * `scripts/check-runtime-state-durability.ts`.
64380
65479
  */
64381
65480
  durability: "restored",
65481
+ /**
65482
+ * History (D850): none — encoder configuration.
65483
+ */
65484
+ history: "none",
64382
65485
  /** Clock fields: written, but excluded from the compare that decides
64383
65486
  * whether persisting is worth a SQLite commit. */
64384
65487
  volatileStateFields: ["lastFetchedAt"]
@@ -64434,6 +65537,10 @@ var switchCapability = {
64434
65537
  * `scripts/check-runtime-state-durability.ts`.
64435
65538
  */
64436
65539
  durability: "restored",
65540
+ /**
65541
+ * History (D850): recorded series.
65542
+ */
65543
+ history: { fields: { on: { kind: "boolean" } } },
64437
65544
  /** Clock fields: written, but excluded from the compare that decides
64438
65545
  * whether persisting is worth a SQLite commit. */
64439
65546
  volatileStateFields: ["lastChangedAt"],
@@ -64448,6 +65555,21 @@ var switchCapability = {
64448
65555
  }
64449
65556
  }] }
64450
65557
  };
65558
+ /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
65559
+ function hasControlCharacter(value) {
65560
+ for (const char of value) {
65561
+ const code = char.codePointAt(0) ?? 0;
65562
+ if (code <= 31 || code >= 127 && code <= 159) return true;
65563
+ }
65564
+ return false;
65565
+ }
65566
+ string().transform((value) => value.trim()).pipe(string().min(1, "The server name cannot be empty").max(48, `The server name is at most 48 characters`).refine((value) => !hasControlCharacter(value), { message: "The server name cannot contain control characters" }));
65567
+ /** What every reader gets: the name to show, and whether the hub chose it itself. */
65568
+ var ServerNameInfoSchema = object({
65569
+ name: string(),
65570
+ /** `true` when nobody named the hub: `name` is the machine hostname. */
65571
+ isDefault: boolean()
65572
+ });
64451
65573
  /**
64452
65574
  * system — system-scoped singleton capability exposing hub-level
64453
65575
  * health, feature flags, network interface enumeration, and the
@@ -64477,6 +65599,12 @@ var FeatureManifestSchema = object({
64477
65599
  backup: boolean(),
64478
65600
  repl: boolean()
64479
65601
  });
65602
+ /**
65603
+ * `system.info`: the feature flags plus the hub's human name (D861). The name is
65604
+ * `{ name, isDefault }` — `isDefault: true` means nobody named the hub and `name`
65605
+ * is the machine hostname.
65606
+ */
65607
+ var SystemInfoSchema = FeatureManifestSchema.extend({ serverName: ServerNameInfoSchema });
64480
65608
  var HealthStatusSchema = object({
64481
65609
  status: literal("ok"),
64482
65610
  uptime: number()
@@ -64949,7 +66077,7 @@ var LoggingSettingsStateSchema = object({
64949
66077
  opsLogRetentionDays: number().int().min(0),
64950
66078
  persisted: boolean()
64951
66079
  });
64952
- method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
66080
+ method(_void(), SystemInfoSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
64953
66081
  kind: "mutation",
64954
66082
  auth: "admin"
64955
66083
  }), method(_void(), _void(), {
@@ -64995,6 +66123,10 @@ var tamperCapability = {
64995
66123
  * `scripts/check-runtime-state-durability.ts`.
64996
66124
  */
64997
66125
  durability: "restored",
66126
+ /**
66127
+ * History (D850): recorded series.
66128
+ */
66129
+ history: { fields: { tampered: { kind: "boolean" } } },
64998
66130
  /** Clock fields: written, but excluded from the compare that decides
64999
66131
  * whether persisting is worth a SQLite commit. */
65000
66132
  volatileStateFields: ["lastChangedAt"]
@@ -65050,6 +66182,14 @@ var temperatureSensorCapability = {
65050
66182
  * `scripts/check-runtime-state-durability.ts`.
65051
66183
  */
65052
66184
  durability: "restored",
66185
+ /**
66186
+ * History (D850): recorded series.
66187
+ */
66188
+ history: { fields: { celsius: {
66189
+ kind: "gauge",
66190
+ unit: "°C",
66191
+ deadband: .1
66192
+ } } },
65053
66193
  /** Clock fields: written, but excluded from the compare that decides
65054
66194
  * whether persisting is worth a SQLite commit. */
65055
66195
  volatileStateFields: ["lastFetchedAt"]
@@ -65128,7 +66268,11 @@ var updateCapability = {
65128
66268
  * See `RuntimeStateDurability`. Enforced by
65129
66269
  * `scripts/check-runtime-state-durability.ts`.
65130
66270
  */
65131
- durability: "session"
66271
+ durability: "session",
66272
+ /**
66273
+ * History (D850): none — text and state.
66274
+ */
66275
+ history: "none"
65132
66276
  };
65133
66277
  var UserSummarySchema = object({
65134
66278
  id: string(),
@@ -65485,7 +66629,37 @@ var vacuumControlCapability = {
65485
66629
  * See `RuntimeStateDurability`. Enforced by
65486
66630
  * `scripts/check-runtime-state-durability.ts`.
65487
66631
  */
65488
- durability: "session"
66632
+ durability: "session",
66633
+ /**
66634
+ * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
66635
+ */
66636
+ history: { fields: {
66637
+ batteryLevel: {
66638
+ kind: "gauge",
66639
+ unit: "%",
66640
+ deadband: 2
66641
+ },
66642
+ "cleanWater.level": {
66643
+ kind: "gauge",
66644
+ unit: "%",
66645
+ deadband: 2
66646
+ },
66647
+ "dirtyWater.level": {
66648
+ kind: "gauge",
66649
+ unit: "%",
66650
+ deadband: 2
66651
+ },
66652
+ "detergent.level": {
66653
+ kind: "gauge",
66654
+ unit: "%",
66655
+ deadband: 2
66656
+ },
66657
+ "dustBin.level": {
66658
+ kind: "gauge",
66659
+ unit: "%",
66660
+ deadband: 2
66661
+ }
66662
+ } }
65489
66663
  };
65490
66664
  var ValveStatusSchema = object({
65491
66665
  /** Lifecycle state of the valve. */
@@ -65544,7 +66718,15 @@ var valveCapability = {
65544
66718
  * See `RuntimeStateDurability`. Enforced by
65545
66719
  * `scripts/check-runtime-state-durability.ts`.
65546
66720
  */
65547
- durability: "session"
66721
+ durability: "session",
66722
+ /**
66723
+ * History (D850): recorded series. Actuator tier: position keeps every change.
66724
+ */
66725
+ history: { fields: { position: {
66726
+ kind: "gauge",
66727
+ unit: "%",
66728
+ minIntervalMs: 0
66729
+ } } }
65548
66730
  };
65549
66731
  /**
65550
66732
  * Vibration / shake / impact sensor. Drives Home Assistant
@@ -65574,6 +66756,10 @@ var vibrationCapability = {
65574
66756
  * `scripts/check-runtime-state-durability.ts`.
65575
66757
  */
65576
66758
  durability: "restored",
66759
+ /**
66760
+ * History (D850): recorded series.
66761
+ */
66762
+ history: { fields: { detected: { kind: "boolean" } } },
65577
66763
  /** Clock fields: written, but excluded from the compare that decides
65578
66764
  * whether persisting is worth a SQLite commit. */
65579
66765
  volatileStateFields: ["lastChangedAt"]
@@ -65657,7 +66843,22 @@ var waterHeaterCapability = {
65657
66843
  * See `RuntimeStateDurability`. Enforced by
65658
66844
  * `scripts/check-runtime-state-durability.ts`.
65659
66845
  */
65660
- durability: "session"
66846
+ durability: "session",
66847
+ /**
66848
+ * History (D850): recorded series. The schema carries no unit; providers publish Celsius. Setpoint keeps every change.
66849
+ */
66850
+ history: { fields: {
66851
+ currentTemp: {
66852
+ kind: "gauge",
66853
+ unit: "°C",
66854
+ deadband: .5
66855
+ },
66856
+ targetTemp: {
66857
+ kind: "gauge",
66858
+ unit: "°C",
66859
+ minIntervalMs: 0
66860
+ }
66861
+ } }
65661
66862
  };
65662
66863
  /**
65663
66864
  * Weather provider cap. Models HA `weather.*` entities — a read-only
@@ -65723,7 +66924,32 @@ var weatherCapability = {
65723
66924
  * See `RuntimeStateDurability`. Enforced by
65724
66925
  * `scripts/check-runtime-state-durability.ts`.
65725
66926
  */
65726
- durability: "session"
66927
+ durability: "session",
66928
+ /**
66929
+ * History (D850): recorded series. Units follow the sibling `*Unit` fields.
66930
+ */
66931
+ history: { fields: {
66932
+ temperature: {
66933
+ kind: "gauge",
66934
+ unitFrom: "temperatureUnit",
66935
+ deadband: .2
66936
+ },
66937
+ humidity: {
66938
+ kind: "gauge",
66939
+ unit: "%",
66940
+ deadband: 1
66941
+ },
66942
+ pressure: {
66943
+ kind: "gauge",
66944
+ unitFrom: "pressureUnit",
66945
+ deadband: .5
66946
+ },
66947
+ windSpeed: {
66948
+ kind: "gauge",
66949
+ unitFrom: "windSpeedUnit",
66950
+ deadband: .5
66951
+ }
66952
+ } }
65727
66953
  };
65728
66954
  /**
65729
66955
  * Per-zone occupancy aggregation produced by the analytics frame
@@ -65965,7 +67191,11 @@ var zoneAnalyticsCapability = {
65965
67191
  * See `RuntimeStateDurability`. Enforced by
65966
67192
  * `scripts/check-runtime-state-durability.ts`.
65967
67193
  */
65968
- durability: "session"
67194
+ durability: "session",
67195
+ /**
67196
+ * History (D850): none — occupancy is the addon series `pipeline-analytics/occupancy`; the rest is per-zone arrays keyed by runtime ids.
67197
+ */
67198
+ history: "none"
65969
67199
  };
65970
67200
  /**
65971
67201
  * Stages a {@link ZoneRule} can apply to. Discriminator on the rules
@@ -66050,7 +67280,11 @@ var zoneRulesCapability = {
66050
67280
  * See `RuntimeStateDurability`. Enforced by
66051
67281
  * `scripts/check-runtime-state-durability.ts`.
66052
67282
  */
66053
- durability: "restored"
67283
+ durability: "restored",
67284
+ /**
67285
+ * History (D850): none — configuration arrays.
67286
+ */
67287
+ history: "none"
66054
67288
  };
66055
67289
  /**
66056
67290
  * `training-provider` — ONE cloud that can run the CamStack trainer.
@@ -69215,6 +70449,54 @@ Object.freeze({
69215
70449
  addonId: null,
69216
70450
  access: "create"
69217
70451
  },
70452
+ "deviceCredentials.deleteDeviceCredential": {
70453
+ capName: "device-credentials",
70454
+ capScope: "system",
70455
+ addonId: null,
70456
+ access: "delete"
70457
+ },
70458
+ "deviceCredentials.getDeviceCaStatus": {
70459
+ capName: "device-credentials",
70460
+ capScope: "system",
70461
+ addonId: null,
70462
+ access: "view"
70463
+ },
70464
+ "deviceCredentials.getDeviceCertificateSettings": {
70465
+ capName: "device-credentials",
70466
+ capScope: "system",
70467
+ addonId: null,
70468
+ access: "view"
70469
+ },
70470
+ "deviceCredentials.listDeviceCredentials": {
70471
+ capName: "device-credentials",
70472
+ capScope: "system",
70473
+ addonId: null,
70474
+ access: "view"
70475
+ },
70476
+ "deviceCredentials.renameDeviceCredential": {
70477
+ capName: "device-credentials",
70478
+ capScope: "system",
70479
+ addonId: null,
70480
+ access: "create"
70481
+ },
70482
+ "deviceCredentials.revokeDeviceCredential": {
70483
+ capName: "device-credentials",
70484
+ capScope: "system",
70485
+ addonId: null,
70486
+ access: "delete"
70487
+ },
70488
+ "deviceCredentials.setDeviceCertificateSettings": {
70489
+ capName: "device-credentials",
70490
+ capScope: "system",
70491
+ addonId: null,
70492
+ access: "create"
70493
+ },
70494
+ "deviceCredentials.startEnrollment": {
70495
+ capName: "device-credentials",
70496
+ capScope: "system",
70497
+ addonId: null,
70498
+ access: "create"
70499
+ },
69218
70500
  "deviceDiscovery.adoptDevice": {
69219
70501
  capName: "device-discovery",
69220
70502
  capScope: "device",
@@ -69317,6 +70599,66 @@ Object.freeze({
69317
70599
  addonId: null,
69318
70600
  access: "create"
69319
70601
  },
70602
+ "deviceHistory.declareSeries": {
70603
+ capName: "device-history",
70604
+ capScope: "system",
70605
+ addonId: null,
70606
+ access: "create"
70607
+ },
70608
+ "deviceHistory.getDeviceEnabled": {
70609
+ capName: "device-history",
70610
+ capScope: "system",
70611
+ addonId: null,
70612
+ access: "view"
70613
+ },
70614
+ "deviceHistory.getStatus": {
70615
+ capName: "device-history",
70616
+ capScope: "system",
70617
+ addonId: null,
70618
+ access: "view"
70619
+ },
70620
+ "deviceHistory.listNodeSeries": {
70621
+ capName: "device-history",
70622
+ capScope: "system",
70623
+ addonId: null,
70624
+ access: "view"
70625
+ },
70626
+ "deviceHistory.listSeries": {
70627
+ capName: "device-history",
70628
+ capScope: "system",
70629
+ addonId: null,
70630
+ access: "view"
70631
+ },
70632
+ "deviceHistory.query": {
70633
+ capName: "device-history",
70634
+ capScope: "system",
70635
+ addonId: null,
70636
+ access: "view"
70637
+ },
70638
+ "deviceHistory.queryNode": {
70639
+ capName: "device-history",
70640
+ capScope: "system",
70641
+ addonId: null,
70642
+ access: "view"
70643
+ },
70644
+ "deviceHistory.record": {
70645
+ capName: "device-history",
70646
+ capScope: "system",
70647
+ addonId: null,
70648
+ access: "create"
70649
+ },
70650
+ "deviceHistory.recordBuckets": {
70651
+ capName: "device-history",
70652
+ capScope: "system",
70653
+ addonId: null,
70654
+ access: "create"
70655
+ },
70656
+ "deviceHistory.setDeviceEnabled": {
70657
+ capName: "device-history",
70658
+ capScope: "system",
70659
+ addonId: null,
70660
+ access: "create"
70661
+ },
69320
70662
  "deviceManager.addLocation": {
69321
70663
  capName: "device-manager",
69322
70664
  capScope: "system",
@@ -69395,6 +70737,12 @@ Object.freeze({
69395
70737
  addonId: null,
69396
70738
  access: "create"
69397
70739
  },
70740
+ "deviceManager.cleanupDeletedDevicesData": {
70741
+ capName: "device-manager",
70742
+ capScope: "system",
70743
+ addonId: null,
70744
+ access: "create"
70745
+ },
69398
70746
  "deviceManager.createDevice": {
69399
70747
  capName: "device-manager",
69400
70748
  capScope: "system",
@@ -69575,6 +70923,12 @@ Object.freeze({
69575
70923
  addonId: null,
69576
70924
  access: "view"
69577
70925
  },
70926
+ "deviceManager.listDeletedSince": {
70927
+ capName: "device-manager",
70928
+ capScope: "system",
70929
+ addonId: null,
70930
+ access: "view"
70931
+ },
69578
70932
  "deviceManager.listDeviceIdsByCaps": {
69579
70933
  capName: "device-manager",
69580
70934
  capScope: "system",
@@ -69983,6 +71337,18 @@ Object.freeze({
69983
71337
  addonId: null,
69984
71338
  access: "create"
69985
71339
  },
71340
+ "deviceRemovalHook.listDeviceData": {
71341
+ capName: "device-removal-hook",
71342
+ capScope: "system",
71343
+ addonId: null,
71344
+ access: "view"
71345
+ },
71346
+ "deviceRemovalHook.onDeviceRemoved": {
71347
+ capName: "device-removal-hook",
71348
+ capScope: "system",
71349
+ addonId: null,
71350
+ access: "create"
71351
+ },
69986
71352
  "deviceState.claimFields": {
69987
71353
  capName: "device-state",
69988
71354
  capScope: "system",
@@ -70415,6 +71781,12 @@ Object.freeze({
70415
71781
  addonId: null,
70416
71782
  access: "delete"
70417
71783
  },
71784
+ "keychain.deleteDeviceScope": {
71785
+ capName: "keychain",
71786
+ capScope: "system",
71787
+ addonId: null,
71788
+ access: "delete"
71789
+ },
70418
71790
  "keychain.getState": {
70419
71791
  capName: "keychain",
70420
71792
  capScope: "system",
@@ -71375,6 +72747,54 @@ Object.freeze({
71375
72747
  addonId: null,
71376
72748
  access: "create"
71377
72749
  },
72750
+ "nodeCertificates.confirmMeshLeaf": {
72751
+ capName: "node-certificates",
72752
+ capScope: "system",
72753
+ addonId: null,
72754
+ access: "create"
72755
+ },
72756
+ "nodeCertificates.forgetHub": {
72757
+ capName: "node-certificates",
72758
+ capScope: "system",
72759
+ addonId: null,
72760
+ access: "delete"
72761
+ },
72762
+ "nodeCertificates.getCertificates": {
72763
+ capName: "node-certificates",
72764
+ capScope: "system",
72765
+ addonId: null,
72766
+ access: "view"
72767
+ },
72768
+ "nodeCertificates.installHttpsCertificate": {
72769
+ capName: "node-certificates",
72770
+ capScope: "system",
72771
+ addonId: null,
72772
+ access: "create"
72773
+ },
72774
+ "nodeCertificates.installMeshLeaf": {
72775
+ capName: "node-certificates",
72776
+ capScope: "system",
72777
+ addonId: null,
72778
+ access: "create"
72779
+ },
72780
+ "nodeCertificates.prepareHttpsCertificate": {
72781
+ capName: "node-certificates",
72782
+ capScope: "system",
72783
+ addonId: null,
72784
+ access: "create"
72785
+ },
72786
+ "nodeCertificates.prepareMeshRenewal": {
72787
+ capName: "node-certificates",
72788
+ capScope: "system",
72789
+ addonId: null,
72790
+ access: "create"
72791
+ },
72792
+ "nodeCertificates.rollbackMeshLeaf": {
72793
+ capName: "node-certificates",
72794
+ capScope: "system",
72795
+ addonId: null,
72796
+ access: "create"
72797
+ },
71378
72798
  "nodes.clusterAddonStatus": {
71379
72799
  capName: "nodes",
71380
72800
  capScope: "system",
@@ -76066,6 +77486,26 @@ Object.freeze({
76066
77486
  form: "single",
76067
77487
  optional: false
76068
77488
  }],
77489
+ "deviceHistory.getDeviceEnabled": [{
77490
+ name: "deviceId",
77491
+ form: "single",
77492
+ optional: false
77493
+ }],
77494
+ "deviceHistory.listSeries": [{
77495
+ name: "deviceId",
77496
+ form: "single",
77497
+ optional: false
77498
+ }],
77499
+ "deviceHistory.query": [{
77500
+ name: "deviceId",
77501
+ form: "single",
77502
+ optional: false
77503
+ }],
77504
+ "deviceHistory.setDeviceEnabled": [{
77505
+ name: "deviceId",
77506
+ form: "single",
77507
+ optional: false
77508
+ }],
76069
77509
  "deviceManager.adoptionRelease": [{
76070
77510
  name: "camDeviceId",
76071
77511
  form: "single",
@@ -76359,6 +77799,11 @@ Object.freeze({
76359
77799
  form: "single",
76360
77800
  optional: false
76361
77801
  }],
77802
+ "deviceRemovalHook.onDeviceRemoved": [{
77803
+ name: "deviceId",
77804
+ form: "single",
77805
+ optional: false
77806
+ }],
76362
77807
  "deviceState.claimFields": [{
76363
77808
  name: "deviceId",
76364
77809
  form: "single",
@@ -76548,6 +77993,11 @@ Object.freeze({
76548
77993
  form: "single",
76549
77994
  optional: false
76550
77995
  }],
77996
+ "keychain.deleteDeviceScope": [{
77997
+ name: "deviceId",
77998
+ form: "single",
77999
+ optional: false
78000
+ }],
76551
78001
  "lawnMowerControl.dock": [{
76552
78002
  name: "deviceId",
76553
78003
  form: "single",
@@ -78244,6 +79694,7 @@ Object.freeze({
78244
79694
  "network-access": "ingress",
78245
79695
  "smtp-provider": "email"
78246
79696
  });
79697
+ DeviceType.Camera;
78247
79698
  var G711_SCALE_CORRECTION_DB = {
78248
79699
  PCMU: 20 * Math.log10(4),
78249
79700
  PCMA: 20 * Math.log10(8)
@@ -81028,6 +82479,8 @@ function eventKindLabel(kind, locale) {
81028
82479
  const key = kind.trim().toLowerCase();
81029
82480
  return isEventKindLabelKey(key) ? EVENT_KIND_LABELS[key][locale] : kind;
81030
82481
  }
82482
+ AppPageLangSchema.options;
82483
+ record(string().min(1), string());
81031
82484
  /**
81032
82485
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
81033
82486
  *
@@ -81456,6 +82909,32 @@ function slideInsideFrame(rect, frameWidth, frameHeight) {
81456
82909
  h
81457
82910
  };
81458
82911
  }
82912
+ /** Slider bounds. `0` is "disabled"; anything in 1..9 is raised to `min`. */
82913
+ var FACE_RESCORE_INTERVAL_FIELD = {
82914
+ min: 0,
82915
+ max: 1440,
82916
+ step: 5,
82917
+ default: 60
82918
+ };
82919
+ /**
82920
+ * Narrow a stored value to minutes. `0` ⇒ disabled; a positive value under
82921
+ * {@link FACE_RESCORE_INTERVAL_MIN_RUNNING} is raised to it; junk or absent ⇒
82922
+ * the default (an unreadable setting must not switch the job off nor storm it).
82923
+ */
82924
+ function readFaceRescoreIntervalMinutes(value) {
82925
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return FACE_RESCORE_INTERVAL_FIELD.default;
82926
+ if (value === 0) return 0;
82927
+ return Math.min(FACE_RESCORE_INTERVAL_FIELD.max, Math.max(10, Math.floor(value)));
82928
+ }
82929
+ /** The interval out of a hydrated payload; a `null` view (mid-boot) is the default. */
82930
+ function pickFaceRescoreIntervalMinutes(view) {
82931
+ if (view === null) return FACE_RESCORE_INTERVAL_FIELD.default;
82932
+ for (const section of view.sections) for (const entry of section.fields) {
82933
+ if (typeof entry !== "object" || entry === null || !("key" in entry)) continue;
82934
+ if (entry.key === "faceRescoreIntervalMinutes") return readFaceRescoreIntervalMinutes("value" in entry ? entry.value : void 0);
82935
+ }
82936
+ return FACE_RESCORE_INTERVAL_FIELD.default;
82937
+ }
81459
82938
  /**
81460
82939
  * WHICH delivered frames the decode worker retains a native copy of.
81461
82940
  *
@@ -81940,6 +83419,76 @@ function encodeVectorBase64(vector) {
81940
83419
  function vectorDimFromBase64(encoded) {
81941
83420
  return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
81942
83421
  }
83422
+ /** How often an implementer re-asks for tombstones after its start-up pass. */
83423
+ var REMOVAL_RECONCILE_INTERVAL_MS = 360 * 60 * 1e3;
83424
+ /** One reconcile pass over every tombstone inside the retention window. */
83425
+ async function reconcileRemovedDevices(opts) {
83426
+ const now = opts.now ?? (() => Date.now());
83427
+ const api = opts.api;
83428
+ if (api === void 0) {
83429
+ opts.logger.warn("device removal reconcile skipped — no device-manager api");
83430
+ return {
83431
+ read: false,
83432
+ applied: 0,
83433
+ failed: 0
83434
+ };
83435
+ }
83436
+ let tombstones;
83437
+ try {
83438
+ tombstones = await api.deviceManager.listDeletedSince.query({ sinceMs: now() - DEVICE_TOMBSTONE_RETENTION_MS });
83439
+ } catch (err) {
83440
+ opts.logger.warn("device removal reconcile skipped — tombstones unreadable, nothing deleted", { meta: { error: errMsg(err) } });
83441
+ return {
83442
+ read: false,
83443
+ applied: 0,
83444
+ failed: 0
83445
+ };
83446
+ }
83447
+ let applied = 0;
83448
+ let failed = 0;
83449
+ for (const tombstone of tombstones) try {
83450
+ const result = await opts.remove(tombstone);
83451
+ applied += 1;
83452
+ if (Object.values(result.counts).reduce((sum, n) => sum + n, 0) > 0) opts.logger.info("device removal reconcile cleaned a missed deletion", {
83453
+ tags: { deviceId: tombstone.deviceId },
83454
+ meta: {
83455
+ counts: result.counts,
83456
+ deletedAt: tombstone.deletedAt
83457
+ }
83458
+ });
83459
+ } catch (err) {
83460
+ failed += 1;
83461
+ opts.logger.warn("device removal reconcile failed for a device — retried next pass", {
83462
+ tags: { deviceId: tombstone.deviceId },
83463
+ meta: { error: errMsg(err) }
83464
+ });
83465
+ }
83466
+ return {
83467
+ read: true,
83468
+ applied,
83469
+ failed
83470
+ };
83471
+ }
83472
+ /**
83473
+ * Run the reconcile now and then periodically. Returns the disposer. The timer
83474
+ * is unref'd and a pass never overlaps the previous one.
83475
+ */
83476
+ function armRemovalReconcile(opts) {
83477
+ let running = false;
83478
+ const pass = () => {
83479
+ if (running) return;
83480
+ running = true;
83481
+ reconcileRemovedDevices(opts).catch((err) => {
83482
+ opts.logger.warn("device removal reconcile pass crashed", { meta: { error: errMsg(err) } });
83483
+ }).finally(() => {
83484
+ running = false;
83485
+ });
83486
+ };
83487
+ pass();
83488
+ const timer = setInterval(pass, REMOVAL_RECONCILE_INTERVAL_MS);
83489
+ timer.unref?.();
83490
+ return () => clearInterval(timer);
83491
+ }
81943
83492
  //#endregion
81944
83493
  //#region src/pipeline-analytics/cluster-model-pin.ts
81945
83494
  /**
@@ -82326,6 +83875,12 @@ Object.defineProperty(exports, "CLIP_TEXT_MODELS", {
82326
83875
  return CLIP_TEXT_MODELS;
82327
83876
  }
82328
83877
  });
83878
+ Object.defineProperty(exports, "CLUSTER_MODEL_OWNER_ADDON_ID", {
83879
+ enumerable: true,
83880
+ get: function() {
83881
+ return CLUSTER_MODEL_OWNER_ADDON_ID;
83882
+ }
83883
+ });
82329
83884
  Object.defineProperty(exports, "COCO_TO_MACRO", {
82330
83885
  enumerable: true,
82331
83886
  get: function() {
@@ -83136,6 +84691,12 @@ Object.defineProperty(exports, "applySecureOnArmEdit", {
83136
84691
  return applySecureOnArmEdit;
83137
84692
  }
83138
84693
  });
84694
+ Object.defineProperty(exports, "armRemovalReconcile", {
84695
+ enumerable: true,
84696
+ get: function() {
84697
+ return armRemovalReconcile;
84698
+ }
84699
+ });
83139
84700
  Object.defineProperty(exports, "array", {
83140
84701
  enumerable: true,
83141
84702
  get: function() {
@@ -83280,6 +84841,12 @@ Object.defineProperty(exports, "describeSystemEventFamilyProblem", {
83280
84841
  return describeSystemEventFamilyProblem;
83281
84842
  }
83282
84843
  });
84844
+ Object.defineProperty(exports, "deviceRemovalHookCapability", {
84845
+ enumerable: true,
84846
+ get: function() {
84847
+ return deviceRemovalHookCapability;
84848
+ }
84849
+ });
83283
84850
  Object.defineProperty(exports, "discriminatedUnion", {
83284
84851
  enumerable: true,
83285
84852
  get: function() {
@@ -83574,6 +85141,12 @@ Object.defineProperty(exports, "partialRecord", {
83574
85141
  return partialRecord;
83575
85142
  }
83576
85143
  });
85144
+ Object.defineProperty(exports, "pickFaceRescoreIntervalMinutes", {
85145
+ enumerable: true,
85146
+ get: function() {
85147
+ return pickFaceRescoreIntervalMinutes;
85148
+ }
85149
+ });
83577
85150
  Object.defineProperty(exports, "pipelineAnalyticsCapability", {
83578
85151
  enumerable: true,
83579
85152
  get: function() {