@camstack/addon-provider-ecowitt 0.2.128 → 0.2.130

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 (3) hide show
  1. package/dist/addon.js +493 -240
  2. package/dist/addon.mjs +493 -240
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let http = require("http");
3
3
  let events = require("events");
4
4
  let dgram = require("dgram");
5
- //#region ../types/dist/event-category-BvOFi6PY.mjs
5
+ //#region ../types/dist/event-category-DOl51-Ij.mjs
6
6
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
7
7
  EventCategory["SystemBoot"] = "system.boot";
8
8
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -81,9 +81,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
81
81
  /**
82
82
  * The node's one-shot runner boot check (D877): planned runners against the
83
83
  * process service, `degraded` when any is failed, refused or missing. The
84
- * alert centre turns it into one alert and a direct critical push.
84
+ * alert centre turns it into one critical alert.
85
85
  */
86
86
  EventCategory["SystemRunnerCheck"] = "system.runner-check";
87
+ /**
88
+ * An alert EPISODE opened or closed, emitted by the alert centre for alerts
89
+ * of severity `critical` or `error` (`AlertEpisodePayload`). The alert
90
+ * centre sends no notification of its own: Notification Center turns this
91
+ * into the `alert-critical` / `alert-error` / `alert-critical-resolved`
92
+ * system-event kinds, and reconciles from the alerts store because a bus
93
+ * event may be dropped (D8, D11).
94
+ */
95
+ EventCategory["AlertEpisode"] = "alert.episode";
87
96
  EventCategory["AddonError"] = "addon.error";
88
97
  EventCategory["AddonPageReady"] = "addon.page-ready";
89
98
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -5408,7 +5417,7 @@ var ZodIssueCode$1 = {
5408
5417
  var ZodFirstPartyTypeKind$1;
5409
5418
  ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
5410
5419
  //#endregion
5411
- //#region ../types/dist/sleep-BegKjwUu.mjs
5420
+ //#region ../types/dist/sleep-BxjU_fJM.mjs
5412
5421
  /**
5413
5422
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5414
5423
  * window to float samples (D455).
@@ -7790,6 +7799,12 @@ function normalizeAddonInitResult(result) {
7790
7799
  if (Array.isArray(result)) return { providers: result };
7791
7800
  return result;
7792
7801
  }
7802
+ /**
7803
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7804
+ * and validates them (`share-token.service.ts` builds its enum from this
7805
+ * list); a data plane names the kinds it ACCEPTS in `share`.
7806
+ */
7807
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7793
7808
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
7794
7809
  var PeerBytesTicketSchema = object({
7795
7810
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -12469,6 +12484,229 @@ var ConvertResultSchema = object({
12469
12484
  files: array(string()).readonly()
12470
12485
  })).readonly()
12471
12486
  });
12487
+ /**
12488
+ * Zod schemas for persisted record types.
12489
+ *
12490
+ * These schemas serve as the single source of truth for types that are
12491
+ * stored in the settings-store backend and retrieved via tRPC. They
12492
+ * replace the manual TypeScript interfaces with schema-derived types,
12493
+ * enabling runtime validation when reading from the backend.
12494
+ *
12495
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
12496
+ * keeps the original name for backward compatibility.
12497
+ */
12498
+ /**
12499
+ * Auth model (v2 — 2026-05-12 caps-only):
12500
+ *
12501
+ * Two principals:
12502
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
12503
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
12504
+ *
12505
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
12506
+ * `super_admin` — collapsed onto the single boolean because every
12507
+ * non-admin caller is governed by the same scope-check rules; the
12508
+ * distinction was only ever used to route role-specific procedures
12509
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12510
+ * with `isAdmin: false` + an explicit scope list.
12511
+ */
12512
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
12513
+ var MethodAccessSchema = _enum([
12514
+ "view",
12515
+ "create",
12516
+ "delete"
12517
+ ]);
12518
+ /**
12519
+ * A single scope grant. Three forms — checked in matcher with OR
12520
+ * semantics; the first match decides whether the call passes:
12521
+ *
12522
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
12523
+ * cap with the matching `scope` declaration. New caps inherit grants
12524
+ * automatically — adding a device cap to the codebase makes it
12525
+ * reachable to every user with `category:device [...]` without a
12526
+ * re-grant. Use this for "family viewer" / "operator" tiers.
12527
+ *
12528
+ * - `addon` — every cap that ships inside a given addon id. Niche;
12529
+ * useful when an integration needs to interact with one specific
12530
+ * addon's surface regardless of how many caps it exports.
12531
+ *
12532
+ * - `capability` — the most precise form. Single cap name. Use for
12533
+ * integration tokens where you want to grant `addons.installPackage`
12534
+ * and nothing else.
12535
+ *
12536
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
12537
+ * "give me everything" escape; there is no wildcard scope.
12538
+ */
12539
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
12540
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
12541
+ var CapScopeSchema = _enum(["device", "system"]);
12542
+ /**
12543
+ * DeviceSelector (scope model v3 — 2026-08-12).
12544
+ *
12545
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
12546
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
12547
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
12548
+ * AFTER the grant was minted — no re-grant, no re-login.
12549
+ *
12550
+ * - `all` — every device in the deployment. The broad viewer/operator
12551
+ * lever without a `category` grant (a `category` grant also covers device
12552
+ * caps that carry no deviceId; `all` is specifically the device set).
12553
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
12554
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
12555
+ * is NOT covered until the grant is edited.
12556
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
12557
+ * DYNAMIC. A device that changes type, or a new device of the type,
12558
+ * re-resolves on the next request.
12559
+ * - `locations` — every device whose operator-assigned `location` label is
12560
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
12561
+ * null/unset location matches NO `locations` selector.
12562
+ */
12563
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
12564
+ object({ kind: literal("all") }),
12565
+ object({
12566
+ kind: literal("ids"),
12567
+ ids: array(number().int()).min(1)
12568
+ }),
12569
+ object({
12570
+ kind: literal("types"),
12571
+ types: array(_enum(DeviceType)).min(1)
12572
+ }),
12573
+ object({
12574
+ kind: literal("locations"),
12575
+ locations: array(string().min(1)).min(1)
12576
+ })
12577
+ ]);
12578
+ var DeviceTokenScopeSchema = object({
12579
+ type: literal("device"),
12580
+ /** The device SET this grant covers — resolved against the live fleet. */
12581
+ selector: DeviceSelectorSchema,
12582
+ access: array(MethodAccessSchema).min(1),
12583
+ /**
12584
+ * Whether a grant on a PARENT device transparently covers its accessory
12585
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
12586
+ * Direction is parent → children ONLY.
12587
+ *
12588
+ * Absent → the matcher DERIVES it from the access flavour: `view`
12589
+ * inherits (a camera viewer sees the camera's accessories), `create` /
12590
+ * `delete` do NOT (actuating/removing a child is an explicit act the
12591
+ * operator must grant on the child, not inherit from the parent). Set it
12592
+ * explicitly to override that default per grant.
12593
+ */
12594
+ includeLinked: boolean().optional()
12595
+ });
12596
+ /**
12597
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
12598
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
12599
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
12600
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
12601
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
12602
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
12603
+ * migration cannot reach a JWT already in a client's hands; parse-time
12604
+ * migration covers both without a flag day. No cast — the raw object is read
12605
+ * through `Reflect.get` (its static type is `unknown`).
12606
+ */
12607
+ function migrateLegacyTokenScope(raw) {
12608
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
12609
+ if (Reflect.get(raw, "type") !== "device") return raw;
12610
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
12611
+ const targets = Reflect.get(raw, "targets");
12612
+ if (!Array.isArray(targets)) return raw;
12613
+ return {
12614
+ type: "device",
12615
+ selector: {
12616
+ kind: "ids",
12617
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
12618
+ },
12619
+ access: Reflect.get(raw, "access")
12620
+ };
12621
+ }
12622
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
12623
+ object({
12624
+ type: literal("category"),
12625
+ target: CapScopeSchema,
12626
+ access: array(MethodAccessSchema).min(1)
12627
+ }),
12628
+ object({
12629
+ type: literal("capability"),
12630
+ target: string(),
12631
+ access: array(MethodAccessSchema).min(1)
12632
+ }),
12633
+ object({
12634
+ type: literal("addon"),
12635
+ target: string(),
12636
+ access: array(MethodAccessSchema).min(1)
12637
+ }),
12638
+ DeviceTokenScopeSchema
12639
+ ]));
12640
+ object({
12641
+ id: string(),
12642
+ username: string(),
12643
+ passwordHash: string(),
12644
+ /**
12645
+ * Admin bypass. When true, the middleware skips the scope-access
12646
+ * check entirely. There is no other axis of privilege; the legacy
12647
+ * role enum collapsed onto this boolean in v2.
12648
+ */
12649
+ isAdmin: boolean().default(false),
12650
+ allowedProviders: AllowedProviderSchema,
12651
+ allowedDevices: AllowedDevicesSchema,
12652
+ /**
12653
+ * Scopes granted to this user. Admins bypass; their `scopes` is
12654
+ * ignored. Non-admins without scopes are locked out of every
12655
+ * protected call.
12656
+ */
12657
+ scopes: array(TokenScopeSchema).default([]),
12658
+ createdAt: number(),
12659
+ updatedAt: number()
12660
+ });
12661
+ object({
12662
+ id: string(),
12663
+ label: string(),
12664
+ isAdmin: boolean().default(false),
12665
+ allowedProviders: AllowedProviderSchema,
12666
+ allowedDevices: AllowedDevicesSchema,
12667
+ tokenHash: string(),
12668
+ tokenPrefix: string(),
12669
+ createdAt: number(),
12670
+ lastUsedAt: number().optional()
12671
+ });
12672
+ object({
12673
+ id: string(),
12674
+ userId: string(),
12675
+ name: string(),
12676
+ tokenHash: string(),
12677
+ tokenPrefix: string(),
12678
+ scopes: array(TokenScopeSchema),
12679
+ expiresAt: number().nullish(),
12680
+ lastUsedAt: number().nullish(),
12681
+ createdAt: number()
12682
+ });
12683
+ /** What a share-view grant lets its holder see. */
12684
+ var ShareViewGrantSchema = object({
12685
+ kind: _enum(SHARE_VIEW_KINDS),
12686
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
12687
+ /** Talk-back, opt-in at mint time; absent means off. */
12688
+ talk: boolean().optional()
12689
+ });
12690
+ var ShareViewScopeSchema = object({
12691
+ type: literal("share-view"),
12692
+ grant: ShareViewGrantSchema
12693
+ });
12694
+ var AddonRoutesScopeSchema = object({
12695
+ type: literal("addon-routes"),
12696
+ access: array(MethodAccessSchema).min(1)
12697
+ });
12698
+ var CredentialScopeSchema = union([
12699
+ literal("*"),
12700
+ ShareViewScopeSchema,
12701
+ AddonRoutesScopeSchema,
12702
+ TokenScopeSchema
12703
+ ]);
12704
+ object({
12705
+ kind: literal("credential"),
12706
+ sub: string().min(1),
12707
+ jti: string().min(16),
12708
+ scopes: array(CredentialScopeSchema).min(1)
12709
+ });
12472
12710
  _enum(["new-session", "step-up"]);
12473
12711
  /** The languages the hub's app landing pages are written in (D858). */
12474
12712
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -13185,7 +13423,14 @@ var AlertSeveritySchema = _enum([
13185
13423
  ]);
13186
13424
  var AlertActionSchema = object({
13187
13425
  label: string(),
13188
- href: string().optional()
13426
+ href: string().optional(),
13427
+ /**
13428
+ * How `href` is followed. Absent / `app`: an admin-ui route (client-side).
13429
+ * `server`: a route the HUB serves (an addon HTTP route such as an OAuth
13430
+ * start) — the browser must leave the SPA with a full navigation, because
13431
+ * the SPA has no such route and would bounce to the home page.
13432
+ */
13433
+ navigation: _enum(["app", "server"]).optional()
13189
13434
  });
13190
13435
  var AlertStatusSchema = _enum([
13191
13436
  "active",
@@ -42014,6 +42259,9 @@ var NcSystemEventKindSchema = _enum([
42014
42259
  "server-updated",
42015
42260
  "export-completed",
42016
42261
  "backup-completed",
42262
+ "alert-critical",
42263
+ "alert-error",
42264
+ "alert-critical-resolved",
42017
42265
  "camera-online",
42018
42266
  "camera-offline",
42019
42267
  "camera-disabled",
@@ -44049,202 +44297,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
44049
44297
  auth: "admin"
44050
44298
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
44051
44299
  /**
44052
- * Zod schemas for persisted record types.
44053
- *
44054
- * These schemas serve as the single source of truth for types that are
44055
- * stored in the settings-store backend and retrieved via tRPC. They
44056
- * replace the manual TypeScript interfaces with schema-derived types,
44057
- * enabling runtime validation when reading from the backend.
44058
- *
44059
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
44060
- * keeps the original name for backward compatibility.
44061
- */
44062
- /**
44063
- * Auth model (v2 — 2026-05-12 caps-only):
44064
- *
44065
- * Two principals:
44066
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
44067
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
44068
- *
44069
- * No role enum. There used to be `viewer / agent / scoped` and earlier
44070
- * `super_admin` — collapsed onto the single boolean because every
44071
- * non-admin caller is governed by the same scope-check rules; the
44072
- * distinction was only ever used to route role-specific procedures
44073
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
44074
- * with `isAdmin: false` + an explicit scope list.
44075
- */
44076
- /** Per-method access flavour. Materialised on every cap method via codegen. */
44077
- var MethodAccessSchema = _enum([
44078
- "view",
44079
- "create",
44080
- "delete"
44081
- ]);
44082
- /**
44083
- * A single scope grant. Three forms — checked in matcher with OR
44084
- * semantics; the first match decides whether the call passes:
44085
- *
44086
- * - `category` — broadest. `target: 'device' | 'system'` selects every
44087
- * cap with the matching `scope` declaration. New caps inherit grants
44088
- * automatically — adding a device cap to the codebase makes it
44089
- * reachable to every user with `category:device [...]` without a
44090
- * re-grant. Use this for "family viewer" / "operator" tiers.
44091
- *
44092
- * - `addon` — every cap that ships inside a given addon id. Niche;
44093
- * useful when an integration needs to interact with one specific
44094
- * addon's surface regardless of how many caps it exports.
44095
- *
44096
- * - `capability` — the most precise form. Single cap name. Use for
44097
- * integration tokens where you want to grant `addons.installPackage`
44098
- * and nothing else.
44099
- *
44100
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
44101
- * "give me everything" escape; there is no wildcard scope.
44102
- */
44103
- var AllowedProviderSchema = union([literal("*"), array(string())]);
44104
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
44105
- var CapScopeSchema = _enum(["device", "system"]);
44106
- /**
44107
- * DeviceSelector (scope model v3 — 2026-08-12).
44108
- *
44109
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
44110
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
44111
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
44112
- * AFTER the grant was minted — no re-grant, no re-login.
44113
- *
44114
- * - `all` — every device in the deployment. The broad viewer/operator
44115
- * lever without a `category` grant (a `category` grant also covers device
44116
- * caps that carry no deviceId; `all` is specifically the device set).
44117
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
44118
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
44119
- * is NOT covered until the grant is edited.
44120
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
44121
- * DYNAMIC. A device that changes type, or a new device of the type,
44122
- * re-resolves on the next request.
44123
- * - `locations` — every device whose operator-assigned `location` label is
44124
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
44125
- * null/unset location matches NO `locations` selector.
44126
- */
44127
- var DeviceSelectorSchema = discriminatedUnion("kind", [
44128
- object({ kind: literal("all") }),
44129
- object({
44130
- kind: literal("ids"),
44131
- ids: array(number().int()).min(1)
44132
- }),
44133
- object({
44134
- kind: literal("types"),
44135
- types: array(_enum(DeviceType)).min(1)
44136
- }),
44137
- object({
44138
- kind: literal("locations"),
44139
- locations: array(string().min(1)).min(1)
44140
- })
44141
- ]);
44142
- var DeviceTokenScopeSchema = object({
44143
- type: literal("device"),
44144
- /** The device SET this grant covers — resolved against the live fleet. */
44145
- selector: DeviceSelectorSchema,
44146
- access: array(MethodAccessSchema).min(1),
44147
- /**
44148
- * Whether a grant on a PARENT device transparently covers its accessory
44149
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
44150
- * Direction is parent → children ONLY.
44151
- *
44152
- * Absent → the matcher DERIVES it from the access flavour: `view`
44153
- * inherits (a camera viewer sees the camera's accessories), `create` /
44154
- * `delete` do NOT (actuating/removing a child is an explicit act the
44155
- * operator must grant on the child, not inherit from the parent). Set it
44156
- * explicitly to override that default per grant.
44157
- */
44158
- includeLinked: boolean().optional()
44159
- });
44160
- /**
44161
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
44162
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
44163
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
44164
- * EVERY parse path — stored records AND the JWT-carried scope arrays
44165
- * normalised at the request boundary ({@link normalizeTokenScopes} in
44166
- * `device-selector.ts`). Chosen over a one-time DB migration because a
44167
- * migration cannot reach a JWT already in a client's hands; parse-time
44168
- * migration covers both without a flag day. No cast — the raw object is read
44169
- * through `Reflect.get` (its static type is `unknown`).
44170
- */
44171
- function migrateLegacyTokenScope(raw) {
44172
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
44173
- if (Reflect.get(raw, "type") !== "device") return raw;
44174
- if (Reflect.get(raw, "selector") !== void 0) return raw;
44175
- const targets = Reflect.get(raw, "targets");
44176
- if (!Array.isArray(targets)) return raw;
44177
- return {
44178
- type: "device",
44179
- selector: {
44180
- kind: "ids",
44181
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
44182
- },
44183
- access: Reflect.get(raw, "access")
44184
- };
44185
- }
44186
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
44187
- object({
44188
- type: literal("category"),
44189
- target: CapScopeSchema,
44190
- access: array(MethodAccessSchema).min(1)
44191
- }),
44192
- object({
44193
- type: literal("capability"),
44194
- target: string(),
44195
- access: array(MethodAccessSchema).min(1)
44196
- }),
44197
- object({
44198
- type: literal("addon"),
44199
- target: string(),
44200
- access: array(MethodAccessSchema).min(1)
44201
- }),
44202
- DeviceTokenScopeSchema
44203
- ]));
44204
- object({
44205
- id: string(),
44206
- username: string(),
44207
- passwordHash: string(),
44208
- /**
44209
- * Admin bypass. When true, the middleware skips the scope-access
44210
- * check entirely. There is no other axis of privilege; the legacy
44211
- * role enum collapsed onto this boolean in v2.
44212
- */
44213
- isAdmin: boolean().default(false),
44214
- allowedProviders: AllowedProviderSchema,
44215
- allowedDevices: AllowedDevicesSchema,
44216
- /**
44217
- * Scopes granted to this user. Admins bypass; their `scopes` is
44218
- * ignored. Non-admins without scopes are locked out of every
44219
- * protected call.
44220
- */
44221
- scopes: array(TokenScopeSchema).default([]),
44222
- createdAt: number(),
44223
- updatedAt: number()
44224
- });
44225
- object({
44226
- id: string(),
44227
- label: string(),
44228
- isAdmin: boolean().default(false),
44229
- allowedProviders: AllowedProviderSchema,
44230
- allowedDevices: AllowedDevicesSchema,
44231
- tokenHash: string(),
44232
- tokenPrefix: string(),
44233
- createdAt: number(),
44234
- lastUsedAt: number().optional()
44235
- });
44236
- object({
44237
- id: string(),
44238
- userId: string(),
44239
- name: string(),
44240
- tokenHash: string(),
44241
- tokenPrefix: string(),
44242
- scopes: array(TokenScopeSchema),
44243
- expiresAt: number().nullish(),
44244
- lastUsedAt: number().nullish(),
44245
- createdAt: number()
44246
- });
44247
- /**
44248
44300
  * `oauth-integration` — a collection cap by which an addon declares
44249
44301
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
44250
44302
  * Each provider returns a static descriptor; the core enumerates them
@@ -51090,7 +51142,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
51090
51142
  }), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
51091
51143
  kind: "mutation",
51092
51144
  auth: "admin"
51093
- }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51145
+ }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
51146
+ clear: boolean(),
51147
+ repointLocationId: string().optional()
51148
+ }), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51094
51149
  kind: "mutation",
51095
51150
  auth: "admin"
51096
51151
  }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
@@ -55346,6 +55401,11 @@ onStatusChanged: { data: object({
55346
55401
  *
55347
55402
  * `kind: 'poll'` — cloud REST APIs typically have no push channel; the
55348
55403
  * provider refreshes the slice on an interval and eagerly after commands.
55404
+ *
55405
+ * UNKNOWN IS NOT OFF. Every field the appliance reports separately is
55406
+ * nullable: `null` means "not known right now" (the appliance has not said,
55407
+ * the link is down, or the description does not carry it) and is never
55408
+ * rendered or exported as `false` / `0`. `availability` says why.
55349
55409
  */
55350
55410
  var DishwasherStateSchema = _enum([
55351
55411
  "idle",
@@ -55355,43 +55415,155 @@ var DishwasherStateSchema = _enum([
55355
55415
  "error",
55356
55416
  "unavailable"
55357
55417
  ]);
55418
+ /**
55419
+ * The appliance's own operation state, uncollapsed. `state` above is the coarse
55420
+ * view for compact surfaces; this is what the appliance said.
55421
+ */
55422
+ var DishwasherOperationStateSchema = _enum([
55423
+ "Inactive",
55424
+ "Ready",
55425
+ "DelayedStart",
55426
+ "Run",
55427
+ "Pause",
55428
+ "ActionRequired",
55429
+ "Finished",
55430
+ "Error",
55431
+ "Aborting"
55432
+ ]);
55433
+ /**
55434
+ * Why fields may be `null`:
55435
+ * - `available` — the link is up and the description is loaded;
55436
+ * - `offline` — the local link is down (values are unknown, not last-known);
55437
+ * - `description-missing` — the link is up but the appliance's description could not
55438
+ * be loaded, so its values cannot be decoded.
55439
+ */
55440
+ var DishwasherAvailabilitySchema = _enum([
55441
+ "available",
55442
+ "offline",
55443
+ "description-missing"
55444
+ ]);
55358
55445
  var DishwasherConsumableLevelSchema = _enum([
55359
55446
  "ok",
55360
55447
  "low",
55361
55448
  "empty"
55362
55449
  ]);
55363
55450
  var DishwasherStatusSchema = object({
55451
+ availability: DishwasherAvailabilitySchema,
55452
+ /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
55364
55453
  state: DishwasherStateSchema,
55365
- /** Active program id/name, or null when none selected / unknown. */
55454
+ /** The appliance's operation state as reported; null when not known. */
55455
+ operationState: DishwasherOperationStateSchema.nullable(),
55456
+ /** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
55366
55457
  program: string().nullable(),
55367
- /** Program tokens the hardware accepts — drives the UI selector. */
55458
+ /** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
55459
+ selectedProgram: string().nullable(),
55460
+ /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
55368
55461
  availablePrograms: array(string()),
55369
- /** Minutes remaining on the active cycle, or null when not running. */
55370
- remainingMinutes: number().int().nonnegative().nullable(),
55462
+ /** Seconds remaining on the active cycle, or null when not running / not known. */
55463
+ remainingSeconds: number().int().nonnegative().nullable(),
55464
+ /** Seconds the delayed start is set to (time until the cycle starts), or null. */
55465
+ delayedStartSeconds: number().int().nonnegative().nullable(),
55371
55466
  /** Cycle completion 0..100, or null when not applicable. */
55372
55467
  progressPercent: number().min(0).max(100).nullable(),
55373
- /** True when the door is reported open. */
55374
- doorOpen: boolean(),
55375
- /** True when remote start is allowed (door closed, power on, etc.). */
55376
- remoteStartAllowed: boolean(),
55377
- /** Main power / switched-on state. */
55378
- powerOn: boolean(),
55468
+ /** True when the door is reported open; null when the door state is not known. */
55469
+ doorOpen: boolean().nullable(),
55470
+ /** True when the door is latched (locked) during a cycle; null when not reported. */
55471
+ doorLocked: boolean().nullable(),
55472
+ /** True when remote start is allowed (door closed, power on, etc.); null when not known. */
55473
+ remoteStartAllowed: boolean().nullable(),
55474
+ /** True when the appliance accepts remote control now; null when not known. */
55475
+ remoteControlActive: boolean().nullable(),
55476
+ /** True while somebody operates the appliance at its panel; null when not reported. */
55477
+ localControlActive: boolean().nullable(),
55478
+ /** Main power / switched-on state; null when not known. */
55479
+ powerOn: boolean().nullable(),
55480
+ /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
55481
+ powerState: string().nullable(),
55379
55482
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
55380
55483
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55381
- halfLoad: boolean(),
55382
- hygienePlus: boolean(),
55484
+ /** Option states: null when the appliance does not expose the option or has not said. */
55485
+ halfLoad: boolean().nullable(),
55486
+ hygienePlus: boolean().nullable(),
55383
55487
  /** Extra dry option when the appliance exposes it. */
55384
- extraDry: boolean(),
55488
+ extraDry: boolean().nullable(),
55385
55489
  /** Intensive zone (lower basket) when the appliance exposes it. */
55386
- intensiveZone: boolean(),
55490
+ intensiveZone: boolean().nullable(),
55387
55491
  /** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
55388
- varioSpeedPlus: boolean(),
55389
- /** Child lock (controls disabled on the appliance). */
55390
- childLock: boolean(),
55492
+ varioSpeedPlus: boolean().nullable(),
55493
+ /** Child lock (controls disabled on the appliance); null when not known. */
55494
+ childLock: boolean().nullable(),
55495
+ /** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
55496
+ activeEvents: array(string()),
55497
+ /** Numeric error code when the appliance reports one; null otherwise. */
55391
55498
  errorCode: number().nullable(),
55499
+ /** Name of the raised alert-level event while the appliance is in error; null otherwise. */
55392
55500
  errorLabel: string().nullable(),
55501
+ /** Ms epoch of the last value received from the appliance; 0 = never. */
55393
55502
  lastFetchedAt: number()
55394
55503
  });
55504
+ var DeviceIdSchema = number().int().nonnegative();
55505
+ /** A value a program option or setting can take. */
55506
+ var DishwasherValueSchema = union([
55507
+ boolean(),
55508
+ string(),
55509
+ number()
55510
+ ]);
55511
+ var DishwasherAccessSchema = _enum([
55512
+ "none",
55513
+ "read",
55514
+ "readWrite",
55515
+ "writeOnly",
55516
+ "readStatic"
55517
+ ]);
55518
+ /**
55519
+ * One option or setting the appliance declares, with the constraints its description
55520
+ * gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
55521
+ */
55522
+ var DishwasherOptionDescriptorSchema = object({
55523
+ /** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
55524
+ key: string(),
55525
+ /** Last segment of the key, for display. */
55526
+ name: string(),
55527
+ type: _enum([
55528
+ "boolean",
55529
+ "number",
55530
+ "enum",
55531
+ "string"
55532
+ ]),
55533
+ access: DishwasherAccessSchema,
55534
+ /** The appliance reports this entity as currently available. */
55535
+ available: boolean(),
55536
+ /** Unit the description declares for a number; null when it declares none. */
55537
+ unit: string().nullable(),
55538
+ min: number().nullable(),
55539
+ max: number().nullable(),
55540
+ step: number().nullable(),
55541
+ /** Allowed members of an enum; null for other types. */
55542
+ enumValues: array(string()).nullable(),
55543
+ defaultValue: DishwasherValueSchema.nullable()
55544
+ });
55545
+ var DishwasherProgramSchema = object({
55546
+ /** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
55547
+ key: string(),
55548
+ name: string(),
55549
+ /** The appliance currently offers this program. */
55550
+ available: boolean(),
55551
+ /** The options this program lists, with the program-level access / availability / default. */
55552
+ options: array(DishwasherOptionDescriptorSchema)
55553
+ });
55554
+ var DishwasherOptionsSchema = object({
55555
+ availability: DishwasherAvailabilitySchema,
55556
+ /** What the appliance can be told to do, from the commands its description declares. */
55557
+ supportsStart: boolean(),
55558
+ supportsPause: boolean(),
55559
+ supportsResume: boolean(),
55560
+ supportsStop: boolean(),
55561
+ supportsPower: boolean(),
55562
+ /** Every program the description lists, with its options. */
55563
+ programs: array(DishwasherProgramSchema),
55564
+ /** Every option and setting entity the description lists (programs reference these by key). */
55565
+ options: array(DishwasherOptionDescriptorSchema)
55566
+ });
55395
55567
  var dishwasherCapability = {
55396
55568
  name: "dishwasher",
55397
55569
  scope: "device",
@@ -55399,86 +55571,102 @@ var dishwasherCapability = {
55399
55571
  mode: "singleton",
55400
55572
  deviceTypes: [DeviceType.Dishwasher],
55401
55573
  methods: {
55402
- start: method(object({ deviceId: number().int().nonnegative() }), _void(), {
55574
+ /**
55575
+ * Start a program. Without `program` the selected one starts. `options` are
55576
+ * option feature keys; each is checked against the program's constraints.
55577
+ */
55578
+ start: method(object({
55579
+ deviceId: DeviceIdSchema,
55580
+ program: string().min(1).optional(),
55581
+ options: record(string(), DishwasherValueSchema).optional()
55582
+ }), _void(), {
55403
55583
  kind: "mutation",
55404
55584
  auth: "protected"
55405
55585
  }),
55406
- pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
55586
+ pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
55407
55587
  kind: "mutation",
55408
55588
  auth: "protected"
55409
55589
  }),
55410
- stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
55590
+ resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
55591
+ kind: "mutation",
55592
+ auth: "protected"
55593
+ }),
55594
+ stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
55411
55595
  kind: "mutation",
55412
55596
  auth: "protected"
55413
55597
  }),
55598
+ /** Select (not start) a program; refused when the appliance does not offer it. */
55414
55599
  setProgram: method(object({
55415
- deviceId: number().int().nonnegative(),
55600
+ deviceId: DeviceIdSchema,
55416
55601
  program: string().min(1)
55417
55602
  }), _void(), {
55418
55603
  kind: "mutation",
55419
55604
  auth: "protected"
55420
55605
  }),
55421
55606
  setPower: method(object({
55422
- deviceId: number().int().nonnegative(),
55607
+ deviceId: DeviceIdSchema,
55423
55608
  on: boolean()
55424
55609
  }), _void(), {
55425
55610
  kind: "mutation",
55426
55611
  auth: "protected"
55427
55612
  }),
55428
55613
  setHalfLoad: method(object({
55429
- deviceId: number().int().nonnegative(),
55614
+ deviceId: DeviceIdSchema,
55430
55615
  on: boolean()
55431
55616
  }), _void(), {
55432
55617
  kind: "mutation",
55433
55618
  auth: "protected"
55434
55619
  }),
55435
55620
  setHygienePlus: method(object({
55436
- deviceId: number().int().nonnegative(),
55621
+ deviceId: DeviceIdSchema,
55437
55622
  on: boolean()
55438
55623
  }), _void(), {
55439
55624
  kind: "mutation",
55440
55625
  auth: "protected"
55441
55626
  }),
55442
55627
  setExtraDry: method(object({
55443
- deviceId: number().int().nonnegative(),
55628
+ deviceId: DeviceIdSchema,
55444
55629
  on: boolean()
55445
55630
  }), _void(), {
55446
55631
  kind: "mutation",
55447
55632
  auth: "protected"
55448
55633
  }),
55449
55634
  setIntensiveZone: method(object({
55450
- deviceId: number().int().nonnegative(),
55635
+ deviceId: DeviceIdSchema,
55451
55636
  on: boolean()
55452
55637
  }), _void(), {
55453
55638
  kind: "mutation",
55454
55639
  auth: "protected"
55455
55640
  }),
55456
55641
  setVarioSpeedPlus: method(object({
55457
- deviceId: number().int().nonnegative(),
55642
+ deviceId: DeviceIdSchema,
55458
55643
  on: boolean()
55459
55644
  }), _void(), {
55460
55645
  kind: "mutation",
55461
55646
  auth: "protected"
55462
55647
  }),
55463
55648
  setChildLock: method(object({
55464
- deviceId: number().int().nonnegative(),
55649
+ deviceId: DeviceIdSchema,
55465
55650
  on: boolean()
55466
55651
  }), _void(), {
55467
55652
  kind: "mutation",
55468
55653
  auth: "protected"
55469
55654
  }),
55655
+ /**
55656
+ * Write any option or setting by feature key. Refused when the description does
55657
+ * not list it, it is not writable or not available now, or the value is outside
55658
+ * its declared range / members.
55659
+ */
55470
55660
  setOption: method(object({
55471
- deviceId: number().int().nonnegative(),
55661
+ deviceId: DeviceIdSchema,
55472
55662
  key: string().min(1),
55473
- value: union([
55474
- boolean(),
55475
- string(),
55476
- number()
55477
- ])
55663
+ value: DishwasherValueSchema
55478
55664
  }), _void(), {
55479
55665
  kind: "mutation",
55480
55666
  auth: "protected"
55481
- })
55667
+ }),
55668
+ /** What this appliance can do, from its own description — the UI is derived from it. */
55669
+ getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
55482
55670
  },
55483
55671
  status: {
55484
55672
  schema: DishwasherStatusSchema,
@@ -69427,6 +69615,12 @@ Object.freeze({
69427
69615
  addonId: null,
69428
69616
  access: "view"
69429
69617
  },
69618
+ "dishwasher.getOptions": {
69619
+ capName: "dishwasher",
69620
+ capScope: "device",
69621
+ addonId: null,
69622
+ access: "view"
69623
+ },
69430
69624
  "dishwasher.getStatus": {
69431
69625
  capName: "dishwasher",
69432
69626
  capScope: "device",
@@ -69439,6 +69633,12 @@ Object.freeze({
69439
69633
  addonId: null,
69440
69634
  access: "create"
69441
69635
  },
69636
+ "dishwasher.resume": {
69637
+ capName: "dishwasher",
69638
+ capScope: "device",
69639
+ addonId: null,
69640
+ access: "create"
69641
+ },
69442
69642
  "dishwasher.setChildLock": {
69443
69643
  capName: "dishwasher",
69444
69644
  capScope: "device",
@@ -73939,6 +74139,12 @@ Object.freeze({
73939
74139
  addonId: null,
73940
74140
  access: "view"
73941
74141
  },
74142
+ "storageMigration.moverClearance": {
74143
+ capName: "storage-migration",
74144
+ capScope: "system",
74145
+ addonId: null,
74146
+ access: "view"
74147
+ },
73942
74148
  "storageMigration.movers": {
73943
74149
  capName: "storage-migration",
73944
74150
  capScope: "system",
@@ -76132,6 +76338,11 @@ Object.freeze({
76132
76338
  form: "single",
76133
76339
  optional: false
76134
76340
  }],
76341
+ "dishwasher.getOptions": [{
76342
+ name: "deviceId",
76343
+ form: "single",
76344
+ optional: false
76345
+ }],
76135
76346
  "dishwasher.getStatus": [{
76136
76347
  name: "deviceId",
76137
76348
  form: "single",
@@ -76142,6 +76353,11 @@ Object.freeze({
76142
76353
  form: "single",
76143
76354
  optional: false
76144
76355
  }],
76356
+ "dishwasher.resume": [{
76357
+ name: "deviceId",
76358
+ form: "single",
76359
+ optional: false
76360
+ }],
76145
76361
  "dishwasher.setChildLock": [{
76146
76362
  name: "deviceId",
76147
76363
  form: "single",
@@ -78228,6 +78444,9 @@ new Map(Object.entries({
78228
78444
  "wrapper-update-available": "system",
78229
78445
  "backup-completed": "system",
78230
78446
  "export-completed": "system",
78447
+ "alert-critical": "system",
78448
+ "alert-error": "system",
78449
+ "alert-critical-resolved": "system",
78231
78450
  "storage-location-low": "system",
78232
78451
  "storage-location-critical": "system",
78233
78452
  "storage-location-ok": "system",
@@ -78352,6 +78571,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
78352
78571
  "storage-location-ok"
78353
78572
  ]
78354
78573
  },
78574
+ {
78575
+ id: "alerts",
78576
+ family: "system",
78577
+ label: "Alerts",
78578
+ kinds: [
78579
+ "alert-critical",
78580
+ "alert-error",
78581
+ "alert-critical-resolved"
78582
+ ]
78583
+ },
78355
78584
  {
78356
78585
  id: "alarm",
78357
78586
  family: "alarm",
@@ -78396,6 +78625,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
78396
78625
  return [[descriptor.kind, field]];
78397
78626
  })));
78398
78627
  Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
78628
+ object({
78629
+ phase: _enum(["raised", "resolved"]),
78630
+ episodeId: string().min(1),
78631
+ alertId: string().min(1),
78632
+ severity: AlertSeveritySchema,
78633
+ category: string(),
78634
+ title: string(),
78635
+ message: string(),
78636
+ sourceType: string().optional(),
78637
+ sourceId: string().optional(),
78638
+ nodeId: string().optional(),
78639
+ /** The alert's own action link (where the operator acts on it), when it has one. */
78640
+ actionUrl: string().optional(),
78641
+ at: number()
78642
+ });
78399
78643
  var RULE_BODY_ONLY = ["body"];
78400
78644
  var RULE_TEXT = ["title", "body"];
78401
78645
  var BATTERY = ["device-battery-low", "device-battery-normal"];
@@ -78405,6 +78649,11 @@ var TANK = [
78405
78649
  "device-tank-full",
78406
78650
  "device-tank-normal"
78407
78651
  ];
78652
+ var ALERT_EPISODE = [
78653
+ "alert-critical",
78654
+ "alert-error",
78655
+ "alert-critical-resolved"
78656
+ ];
78408
78657
  var UPDATES = [
78409
78658
  "addon-update-available",
78410
78659
  "server-update-available",
@@ -78597,14 +78846,14 @@ var STATE_SUMMARY_VARS = [
78597
78846
  ([...RULE_TEXT], [...CONSUMABLE]),
78598
78847
  ([...RULE_TEXT], [...TANK]),
78599
78848
  [...RULE_TEXT],
78600
- ([...RULE_TEXT], [...UPDATES]),
78601
- ([...RULE_TEXT], [...UPDATES]),
78602
- [...RULE_TEXT],
78849
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
78850
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
78603
78851
  [...RULE_TEXT],
78604
78852
  [...RULE_TEXT],
78605
78853
  [...RULE_TEXT],
78606
78854
  [...RULE_TEXT],
78607
78855
  [...RULE_TEXT],
78856
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78608
78857
  [...RULE_TEXT],
78609
78858
  [...RULE_TEXT],
78610
78859
  [...RULE_TEXT],
@@ -78622,7 +78871,11 @@ var STATE_SUMMARY_VARS = [
78622
78871
  [...RULE_TEXT],
78623
78872
  [...RULE_TEXT],
78624
78873
  [...RULE_TEXT],
78625
- [...RULE_TEXT],
78874
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78875
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78876
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78877
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78878
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
78626
78879
  [...RULE_TEXT],
78627
78880
  [...RULE_TEXT],
78628
78881
  [...RULE_TEXT],