@camstack/addon-provider-petkit 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
@@ -1101,7 +1101,7 @@ var Nodepetkit = class {
1101
1101
  }
1102
1102
  };
1103
1103
  //#endregion
1104
- //#region ../types/dist/event-category-BvOFi6PY.mjs
1104
+ //#region ../types/dist/event-category-DOl51-Ij.mjs
1105
1105
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
1106
1106
  EventCategory["SystemBoot"] = "system.boot";
1107
1107
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1180,9 +1180,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1180
1180
  /**
1181
1181
  * The node's one-shot runner boot check (D877): planned runners against the
1182
1182
  * process service, `degraded` when any is failed, refused or missing. The
1183
- * alert centre turns it into one alert and a direct critical push.
1183
+ * alert centre turns it into one critical alert.
1184
1184
  */
1185
1185
  EventCategory["SystemRunnerCheck"] = "system.runner-check";
1186
+ /**
1187
+ * An alert EPISODE opened or closed, emitted by the alert centre for alerts
1188
+ * of severity `critical` or `error` (`AlertEpisodePayload`). The alert
1189
+ * centre sends no notification of its own: Notification Center turns this
1190
+ * into the `alert-critical` / `alert-error` / `alert-critical-resolved`
1191
+ * system-event kinds, and reconciles from the alerts store because a bus
1192
+ * event may be dropped (D8, D11).
1193
+ */
1194
+ EventCategory["AlertEpisode"] = "alert.episode";
1186
1195
  EventCategory["AddonError"] = "addon.error";
1187
1196
  EventCategory["AddonPageReady"] = "addon.page-ready";
1188
1197
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -6507,7 +6516,7 @@ var ZodIssueCode = {
6507
6516
  var ZodFirstPartyTypeKind;
6508
6517
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6509
6518
  //#endregion
6510
- //#region ../types/dist/sleep-BegKjwUu.mjs
6519
+ //#region ../types/dist/sleep-BxjU_fJM.mjs
6511
6520
  /**
6512
6521
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6513
6522
  * window to float samples (D455).
@@ -8889,6 +8898,12 @@ function normalizeAddonInitResult(result) {
8889
8898
  if (Array.isArray(result)) return { providers: result };
8890
8899
  return result;
8891
8900
  }
8901
+ /**
8902
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
8903
+ * and validates them (`share-token.service.ts` builds its enum from this
8904
+ * list); a data plane names the kinds it ACCEPTS in `share`.
8905
+ */
8906
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
8892
8907
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
8893
8908
  var PeerBytesTicketSchema = object({
8894
8909
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -13554,6 +13569,229 @@ var ConvertResultSchema = object({
13554
13569
  files: array(string()).readonly()
13555
13570
  })).readonly()
13556
13571
  });
13572
+ /**
13573
+ * Zod schemas for persisted record types.
13574
+ *
13575
+ * These schemas serve as the single source of truth for types that are
13576
+ * stored in the settings-store backend and retrieved via tRPC. They
13577
+ * replace the manual TypeScript interfaces with schema-derived types,
13578
+ * enabling runtime validation when reading from the backend.
13579
+ *
13580
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
13581
+ * keeps the original name for backward compatibility.
13582
+ */
13583
+ /**
13584
+ * Auth model (v2 — 2026-05-12 caps-only):
13585
+ *
13586
+ * Two principals:
13587
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
13588
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
13589
+ *
13590
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
13591
+ * `super_admin` — collapsed onto the single boolean because every
13592
+ * non-admin caller is governed by the same scope-check rules; the
13593
+ * distinction was only ever used to route role-specific procedures
13594
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
13595
+ * with `isAdmin: false` + an explicit scope list.
13596
+ */
13597
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
13598
+ var MethodAccessSchema = _enum([
13599
+ "view",
13600
+ "create",
13601
+ "delete"
13602
+ ]);
13603
+ /**
13604
+ * A single scope grant. Three forms — checked in matcher with OR
13605
+ * semantics; the first match decides whether the call passes:
13606
+ *
13607
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
13608
+ * cap with the matching `scope` declaration. New caps inherit grants
13609
+ * automatically — adding a device cap to the codebase makes it
13610
+ * reachable to every user with `category:device [...]` without a
13611
+ * re-grant. Use this for "family viewer" / "operator" tiers.
13612
+ *
13613
+ * - `addon` — every cap that ships inside a given addon id. Niche;
13614
+ * useful when an integration needs to interact with one specific
13615
+ * addon's surface regardless of how many caps it exports.
13616
+ *
13617
+ * - `capability` — the most precise form. Single cap name. Use for
13618
+ * integration tokens where you want to grant `addons.installPackage`
13619
+ * and nothing else.
13620
+ *
13621
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
13622
+ * "give me everything" escape; there is no wildcard scope.
13623
+ */
13624
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
13625
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
13626
+ var CapScopeSchema = _enum(["device", "system"]);
13627
+ /**
13628
+ * DeviceSelector (scope model v3 — 2026-08-12).
13629
+ *
13630
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
13631
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
13632
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
13633
+ * AFTER the grant was minted — no re-grant, no re-login.
13634
+ *
13635
+ * - `all` — every device in the deployment. The broad viewer/operator
13636
+ * lever without a `category` grant (a `category` grant also covers device
13637
+ * caps that carry no deviceId; `all` is specifically the device set).
13638
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
13639
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
13640
+ * is NOT covered until the grant is edited.
13641
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
13642
+ * DYNAMIC. A device that changes type, or a new device of the type,
13643
+ * re-resolves on the next request.
13644
+ * - `locations` — every device whose operator-assigned `location` label is
13645
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
13646
+ * null/unset location matches NO `locations` selector.
13647
+ */
13648
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
13649
+ object({ kind: literal("all") }),
13650
+ object({
13651
+ kind: literal("ids"),
13652
+ ids: array(number().int()).min(1)
13653
+ }),
13654
+ object({
13655
+ kind: literal("types"),
13656
+ types: array(_enum(DeviceType)).min(1)
13657
+ }),
13658
+ object({
13659
+ kind: literal("locations"),
13660
+ locations: array(string().min(1)).min(1)
13661
+ })
13662
+ ]);
13663
+ var DeviceTokenScopeSchema = object({
13664
+ type: literal("device"),
13665
+ /** The device SET this grant covers — resolved against the live fleet. */
13666
+ selector: DeviceSelectorSchema,
13667
+ access: array(MethodAccessSchema).min(1),
13668
+ /**
13669
+ * Whether a grant on a PARENT device transparently covers its accessory
13670
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
13671
+ * Direction is parent → children ONLY.
13672
+ *
13673
+ * Absent → the matcher DERIVES it from the access flavour: `view`
13674
+ * inherits (a camera viewer sees the camera's accessories), `create` /
13675
+ * `delete` do NOT (actuating/removing a child is an explicit act the
13676
+ * operator must grant on the child, not inherit from the parent). Set it
13677
+ * explicitly to override that default per grant.
13678
+ */
13679
+ includeLinked: boolean().optional()
13680
+ });
13681
+ /**
13682
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
13683
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
13684
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
13685
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
13686
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
13687
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
13688
+ * migration cannot reach a JWT already in a client's hands; parse-time
13689
+ * migration covers both without a flag day. No cast — the raw object is read
13690
+ * through `Reflect.get` (its static type is `unknown`).
13691
+ */
13692
+ function migrateLegacyTokenScope(raw) {
13693
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
13694
+ if (Reflect.get(raw, "type") !== "device") return raw;
13695
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
13696
+ const targets = Reflect.get(raw, "targets");
13697
+ if (!Array.isArray(targets)) return raw;
13698
+ return {
13699
+ type: "device",
13700
+ selector: {
13701
+ kind: "ids",
13702
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
13703
+ },
13704
+ access: Reflect.get(raw, "access")
13705
+ };
13706
+ }
13707
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
13708
+ object({
13709
+ type: literal("category"),
13710
+ target: CapScopeSchema,
13711
+ access: array(MethodAccessSchema).min(1)
13712
+ }),
13713
+ object({
13714
+ type: literal("capability"),
13715
+ target: string(),
13716
+ access: array(MethodAccessSchema).min(1)
13717
+ }),
13718
+ object({
13719
+ type: literal("addon"),
13720
+ target: string(),
13721
+ access: array(MethodAccessSchema).min(1)
13722
+ }),
13723
+ DeviceTokenScopeSchema
13724
+ ]));
13725
+ object({
13726
+ id: string(),
13727
+ username: string(),
13728
+ passwordHash: string(),
13729
+ /**
13730
+ * Admin bypass. When true, the middleware skips the scope-access
13731
+ * check entirely. There is no other axis of privilege; the legacy
13732
+ * role enum collapsed onto this boolean in v2.
13733
+ */
13734
+ isAdmin: boolean().default(false),
13735
+ allowedProviders: AllowedProviderSchema,
13736
+ allowedDevices: AllowedDevicesSchema,
13737
+ /**
13738
+ * Scopes granted to this user. Admins bypass; their `scopes` is
13739
+ * ignored. Non-admins without scopes are locked out of every
13740
+ * protected call.
13741
+ */
13742
+ scopes: array(TokenScopeSchema).default([]),
13743
+ createdAt: number(),
13744
+ updatedAt: number()
13745
+ });
13746
+ object({
13747
+ id: string(),
13748
+ label: string(),
13749
+ isAdmin: boolean().default(false),
13750
+ allowedProviders: AllowedProviderSchema,
13751
+ allowedDevices: AllowedDevicesSchema,
13752
+ tokenHash: string(),
13753
+ tokenPrefix: string(),
13754
+ createdAt: number(),
13755
+ lastUsedAt: number().optional()
13756
+ });
13757
+ object({
13758
+ id: string(),
13759
+ userId: string(),
13760
+ name: string(),
13761
+ tokenHash: string(),
13762
+ tokenPrefix: string(),
13763
+ scopes: array(TokenScopeSchema),
13764
+ expiresAt: number().nullish(),
13765
+ lastUsedAt: number().nullish(),
13766
+ createdAt: number()
13767
+ });
13768
+ /** What a share-view grant lets its holder see. */
13769
+ var ShareViewGrantSchema = object({
13770
+ kind: _enum(SHARE_VIEW_KINDS),
13771
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
13772
+ /** Talk-back, opt-in at mint time; absent means off. */
13773
+ talk: boolean().optional()
13774
+ });
13775
+ var ShareViewScopeSchema = object({
13776
+ type: literal("share-view"),
13777
+ grant: ShareViewGrantSchema
13778
+ });
13779
+ var AddonRoutesScopeSchema = object({
13780
+ type: literal("addon-routes"),
13781
+ access: array(MethodAccessSchema).min(1)
13782
+ });
13783
+ var CredentialScopeSchema = union([
13784
+ literal("*"),
13785
+ ShareViewScopeSchema,
13786
+ AddonRoutesScopeSchema,
13787
+ TokenScopeSchema
13788
+ ]);
13789
+ object({
13790
+ kind: literal("credential"),
13791
+ sub: string().min(1),
13792
+ jti: string().min(16),
13793
+ scopes: array(CredentialScopeSchema).min(1)
13794
+ });
13557
13795
  _enum(["new-session", "step-up"]);
13558
13796
  /** The languages the hub's app landing pages are written in (D858). */
13559
13797
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -14270,7 +14508,14 @@ var AlertSeveritySchema = _enum([
14270
14508
  ]);
14271
14509
  var AlertActionSchema = object({
14272
14510
  label: string(),
14273
- href: string().optional()
14511
+ href: string().optional(),
14512
+ /**
14513
+ * How `href` is followed. Absent / `app`: an admin-ui route (client-side).
14514
+ * `server`: a route the HUB serves (an addon HTTP route such as an OAuth
14515
+ * start) — the browser must leave the SPA with a full navigation, because
14516
+ * the SPA has no such route and would bounce to the home page.
14517
+ */
14518
+ navigation: _enum(["app", "server"]).optional()
14274
14519
  });
14275
14520
  var AlertStatusSchema = _enum([
14276
14521
  "active",
@@ -43003,6 +43248,9 @@ var NcSystemEventKindSchema = _enum([
43003
43248
  "server-updated",
43004
43249
  "export-completed",
43005
43250
  "backup-completed",
43251
+ "alert-critical",
43252
+ "alert-error",
43253
+ "alert-critical-resolved",
43006
43254
  "camera-online",
43007
43255
  "camera-offline",
43008
43256
  "camera-disabled",
@@ -45038,202 +45286,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
45038
45286
  auth: "admin"
45039
45287
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
45040
45288
  /**
45041
- * Zod schemas for persisted record types.
45042
- *
45043
- * These schemas serve as the single source of truth for types that are
45044
- * stored in the settings-store backend and retrieved via tRPC. They
45045
- * replace the manual TypeScript interfaces with schema-derived types,
45046
- * enabling runtime validation when reading from the backend.
45047
- *
45048
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
45049
- * keeps the original name for backward compatibility.
45050
- */
45051
- /**
45052
- * Auth model (v2 — 2026-05-12 caps-only):
45053
- *
45054
- * Two principals:
45055
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
45056
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
45057
- *
45058
- * No role enum. There used to be `viewer / agent / scoped` and earlier
45059
- * `super_admin` — collapsed onto the single boolean because every
45060
- * non-admin caller is governed by the same scope-check rules; the
45061
- * distinction was only ever used to route role-specific procedures
45062
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
45063
- * with `isAdmin: false` + an explicit scope list.
45064
- */
45065
- /** Per-method access flavour. Materialised on every cap method via codegen. */
45066
- var MethodAccessSchema = _enum([
45067
- "view",
45068
- "create",
45069
- "delete"
45070
- ]);
45071
- /**
45072
- * A single scope grant. Three forms — checked in matcher with OR
45073
- * semantics; the first match decides whether the call passes:
45074
- *
45075
- * - `category` — broadest. `target: 'device' | 'system'` selects every
45076
- * cap with the matching `scope` declaration. New caps inherit grants
45077
- * automatically — adding a device cap to the codebase makes it
45078
- * reachable to every user with `category:device [...]` without a
45079
- * re-grant. Use this for "family viewer" / "operator" tiers.
45080
- *
45081
- * - `addon` — every cap that ships inside a given addon id. Niche;
45082
- * useful when an integration needs to interact with one specific
45083
- * addon's surface regardless of how many caps it exports.
45084
- *
45085
- * - `capability` — the most precise form. Single cap name. Use for
45086
- * integration tokens where you want to grant `addons.installPackage`
45087
- * and nothing else.
45088
- *
45089
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
45090
- * "give me everything" escape; there is no wildcard scope.
45091
- */
45092
- var AllowedProviderSchema = union([literal("*"), array(string())]);
45093
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
45094
- var CapScopeSchema = _enum(["device", "system"]);
45095
- /**
45096
- * DeviceSelector (scope model v3 — 2026-08-12).
45097
- *
45098
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
45099
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
45100
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
45101
- * AFTER the grant was minted — no re-grant, no re-login.
45102
- *
45103
- * - `all` — every device in the deployment. The broad viewer/operator
45104
- * lever without a `category` grant (a `category` grant also covers device
45105
- * caps that carry no deviceId; `all` is specifically the device set).
45106
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
45107
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
45108
- * is NOT covered until the grant is edited.
45109
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
45110
- * DYNAMIC. A device that changes type, or a new device of the type,
45111
- * re-resolves on the next request.
45112
- * - `locations` — every device whose operator-assigned `location` label is
45113
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
45114
- * null/unset location matches NO `locations` selector.
45115
- */
45116
- var DeviceSelectorSchema = discriminatedUnion("kind", [
45117
- object({ kind: literal("all") }),
45118
- object({
45119
- kind: literal("ids"),
45120
- ids: array(number().int()).min(1)
45121
- }),
45122
- object({
45123
- kind: literal("types"),
45124
- types: array(_enum(DeviceType)).min(1)
45125
- }),
45126
- object({
45127
- kind: literal("locations"),
45128
- locations: array(string().min(1)).min(1)
45129
- })
45130
- ]);
45131
- var DeviceTokenScopeSchema = object({
45132
- type: literal("device"),
45133
- /** The device SET this grant covers — resolved against the live fleet. */
45134
- selector: DeviceSelectorSchema,
45135
- access: array(MethodAccessSchema).min(1),
45136
- /**
45137
- * Whether a grant on a PARENT device transparently covers its accessory
45138
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
45139
- * Direction is parent → children ONLY.
45140
- *
45141
- * Absent → the matcher DERIVES it from the access flavour: `view`
45142
- * inherits (a camera viewer sees the camera's accessories), `create` /
45143
- * `delete` do NOT (actuating/removing a child is an explicit act the
45144
- * operator must grant on the child, not inherit from the parent). Set it
45145
- * explicitly to override that default per grant.
45146
- */
45147
- includeLinked: boolean().optional()
45148
- });
45149
- /**
45150
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
45151
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
45152
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
45153
- * EVERY parse path — stored records AND the JWT-carried scope arrays
45154
- * normalised at the request boundary ({@link normalizeTokenScopes} in
45155
- * `device-selector.ts`). Chosen over a one-time DB migration because a
45156
- * migration cannot reach a JWT already in a client's hands; parse-time
45157
- * migration covers both without a flag day. No cast — the raw object is read
45158
- * through `Reflect.get` (its static type is `unknown`).
45159
- */
45160
- function migrateLegacyTokenScope(raw) {
45161
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
45162
- if (Reflect.get(raw, "type") !== "device") return raw;
45163
- if (Reflect.get(raw, "selector") !== void 0) return raw;
45164
- const targets = Reflect.get(raw, "targets");
45165
- if (!Array.isArray(targets)) return raw;
45166
- return {
45167
- type: "device",
45168
- selector: {
45169
- kind: "ids",
45170
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
45171
- },
45172
- access: Reflect.get(raw, "access")
45173
- };
45174
- }
45175
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
45176
- object({
45177
- type: literal("category"),
45178
- target: CapScopeSchema,
45179
- access: array(MethodAccessSchema).min(1)
45180
- }),
45181
- object({
45182
- type: literal("capability"),
45183
- target: string(),
45184
- access: array(MethodAccessSchema).min(1)
45185
- }),
45186
- object({
45187
- type: literal("addon"),
45188
- target: string(),
45189
- access: array(MethodAccessSchema).min(1)
45190
- }),
45191
- DeviceTokenScopeSchema
45192
- ]));
45193
- object({
45194
- id: string(),
45195
- username: string(),
45196
- passwordHash: string(),
45197
- /**
45198
- * Admin bypass. When true, the middleware skips the scope-access
45199
- * check entirely. There is no other axis of privilege; the legacy
45200
- * role enum collapsed onto this boolean in v2.
45201
- */
45202
- isAdmin: boolean().default(false),
45203
- allowedProviders: AllowedProviderSchema,
45204
- allowedDevices: AllowedDevicesSchema,
45205
- /**
45206
- * Scopes granted to this user. Admins bypass; their `scopes` is
45207
- * ignored. Non-admins without scopes are locked out of every
45208
- * protected call.
45209
- */
45210
- scopes: array(TokenScopeSchema).default([]),
45211
- createdAt: number(),
45212
- updatedAt: number()
45213
- });
45214
- object({
45215
- id: string(),
45216
- label: string(),
45217
- isAdmin: boolean().default(false),
45218
- allowedProviders: AllowedProviderSchema,
45219
- allowedDevices: AllowedDevicesSchema,
45220
- tokenHash: string(),
45221
- tokenPrefix: string(),
45222
- createdAt: number(),
45223
- lastUsedAt: number().optional()
45224
- });
45225
- object({
45226
- id: string(),
45227
- userId: string(),
45228
- name: string(),
45229
- tokenHash: string(),
45230
- tokenPrefix: string(),
45231
- scopes: array(TokenScopeSchema),
45232
- expiresAt: number().nullish(),
45233
- lastUsedAt: number().nullish(),
45234
- createdAt: number()
45235
- });
45236
- /**
45237
45289
  * `oauth-integration` — a collection cap by which an addon declares
45238
45290
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
45239
45291
  * Each provider returns a static descriptor; the core enumerates them
@@ -52079,7 +52131,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
52079
52131
  }), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
52080
52132
  kind: "mutation",
52081
52133
  auth: "admin"
52082
- }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
52134
+ }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
52135
+ clear: boolean(),
52136
+ repointLocationId: string().optional()
52137
+ }), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
52083
52138
  kind: "mutation",
52084
52139
  auth: "admin"
52085
52140
  }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
@@ -56343,6 +56398,11 @@ onStatusChanged: { data: object({
56343
56398
  *
56344
56399
  * `kind: 'poll'` — cloud REST APIs typically have no push channel; the
56345
56400
  * provider refreshes the slice on an interval and eagerly after commands.
56401
+ *
56402
+ * UNKNOWN IS NOT OFF. Every field the appliance reports separately is
56403
+ * nullable: `null` means "not known right now" (the appliance has not said,
56404
+ * the link is down, or the description does not carry it) and is never
56405
+ * rendered or exported as `false` / `0`. `availability` says why.
56346
56406
  */
56347
56407
  var DishwasherStateSchema = _enum([
56348
56408
  "idle",
@@ -56352,43 +56412,155 @@ var DishwasherStateSchema = _enum([
56352
56412
  "error",
56353
56413
  "unavailable"
56354
56414
  ]);
56415
+ /**
56416
+ * The appliance's own operation state, uncollapsed. `state` above is the coarse
56417
+ * view for compact surfaces; this is what the appliance said.
56418
+ */
56419
+ var DishwasherOperationStateSchema = _enum([
56420
+ "Inactive",
56421
+ "Ready",
56422
+ "DelayedStart",
56423
+ "Run",
56424
+ "Pause",
56425
+ "ActionRequired",
56426
+ "Finished",
56427
+ "Error",
56428
+ "Aborting"
56429
+ ]);
56430
+ /**
56431
+ * Why fields may be `null`:
56432
+ * - `available` — the link is up and the description is loaded;
56433
+ * - `offline` — the local link is down (values are unknown, not last-known);
56434
+ * - `description-missing` — the link is up but the appliance's description could not
56435
+ * be loaded, so its values cannot be decoded.
56436
+ */
56437
+ var DishwasherAvailabilitySchema = _enum([
56438
+ "available",
56439
+ "offline",
56440
+ "description-missing"
56441
+ ]);
56355
56442
  var DishwasherConsumableLevelSchema = _enum([
56356
56443
  "ok",
56357
56444
  "low",
56358
56445
  "empty"
56359
56446
  ]);
56360
56447
  var DishwasherStatusSchema = object({
56448
+ availability: DishwasherAvailabilitySchema,
56449
+ /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
56361
56450
  state: DishwasherStateSchema,
56362
- /** Active program id/name, or null when none selected / unknown. */
56451
+ /** The appliance's operation state as reported; null when not known. */
56452
+ operationState: DishwasherOperationStateSchema.nullable(),
56453
+ /** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
56363
56454
  program: string().nullable(),
56364
- /** Program tokens the hardware accepts — drives the UI selector. */
56455
+ /** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
56456
+ selectedProgram: string().nullable(),
56457
+ /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
56365
56458
  availablePrograms: array(string()),
56366
- /** Minutes remaining on the active cycle, or null when not running. */
56367
- remainingMinutes: number().int().nonnegative().nullable(),
56459
+ /** Seconds remaining on the active cycle, or null when not running / not known. */
56460
+ remainingSeconds: number().int().nonnegative().nullable(),
56461
+ /** Seconds the delayed start is set to (time until the cycle starts), or null. */
56462
+ delayedStartSeconds: number().int().nonnegative().nullable(),
56368
56463
  /** Cycle completion 0..100, or null when not applicable. */
56369
56464
  progressPercent: number().min(0).max(100).nullable(),
56370
- /** True when the door is reported open. */
56371
- doorOpen: boolean(),
56372
- /** True when remote start is allowed (door closed, power on, etc.). */
56373
- remoteStartAllowed: boolean(),
56374
- /** Main power / switched-on state. */
56375
- powerOn: boolean(),
56465
+ /** True when the door is reported open; null when the door state is not known. */
56466
+ doorOpen: boolean().nullable(),
56467
+ /** True when the door is latched (locked) during a cycle; null when not reported. */
56468
+ doorLocked: boolean().nullable(),
56469
+ /** True when remote start is allowed (door closed, power on, etc.); null when not known. */
56470
+ remoteStartAllowed: boolean().nullable(),
56471
+ /** True when the appliance accepts remote control now; null when not known. */
56472
+ remoteControlActive: boolean().nullable(),
56473
+ /** True while somebody operates the appliance at its panel; null when not reported. */
56474
+ localControlActive: boolean().nullable(),
56475
+ /** Main power / switched-on state; null when not known. */
56476
+ powerOn: boolean().nullable(),
56477
+ /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56478
+ powerState: string().nullable(),
56376
56479
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
56377
56480
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56378
- halfLoad: boolean(),
56379
- hygienePlus: boolean(),
56481
+ /** Option states: null when the appliance does not expose the option or has not said. */
56482
+ halfLoad: boolean().nullable(),
56483
+ hygienePlus: boolean().nullable(),
56380
56484
  /** Extra dry option when the appliance exposes it. */
56381
- extraDry: boolean(),
56485
+ extraDry: boolean().nullable(),
56382
56486
  /** Intensive zone (lower basket) when the appliance exposes it. */
56383
- intensiveZone: boolean(),
56487
+ intensiveZone: boolean().nullable(),
56384
56488
  /** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
56385
- varioSpeedPlus: boolean(),
56386
- /** Child lock (controls disabled on the appliance). */
56387
- childLock: boolean(),
56489
+ varioSpeedPlus: boolean().nullable(),
56490
+ /** Child lock (controls disabled on the appliance); null when not known. */
56491
+ childLock: boolean().nullable(),
56492
+ /** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
56493
+ activeEvents: array(string()),
56494
+ /** Numeric error code when the appliance reports one; null otherwise. */
56388
56495
  errorCode: number().nullable(),
56496
+ /** Name of the raised alert-level event while the appliance is in error; null otherwise. */
56389
56497
  errorLabel: string().nullable(),
56498
+ /** Ms epoch of the last value received from the appliance; 0 = never. */
56390
56499
  lastFetchedAt: number()
56391
56500
  });
56501
+ var DeviceIdSchema = number().int().nonnegative();
56502
+ /** A value a program option or setting can take. */
56503
+ var DishwasherValueSchema = union([
56504
+ boolean(),
56505
+ string(),
56506
+ number()
56507
+ ]);
56508
+ var DishwasherAccessSchema = _enum([
56509
+ "none",
56510
+ "read",
56511
+ "readWrite",
56512
+ "writeOnly",
56513
+ "readStatic"
56514
+ ]);
56515
+ /**
56516
+ * One option or setting the appliance declares, with the constraints its description
56517
+ * gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
56518
+ */
56519
+ var DishwasherOptionDescriptorSchema = object({
56520
+ /** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
56521
+ key: string(),
56522
+ /** Last segment of the key, for display. */
56523
+ name: string(),
56524
+ type: _enum([
56525
+ "boolean",
56526
+ "number",
56527
+ "enum",
56528
+ "string"
56529
+ ]),
56530
+ access: DishwasherAccessSchema,
56531
+ /** The appliance reports this entity as currently available. */
56532
+ available: boolean(),
56533
+ /** Unit the description declares for a number; null when it declares none. */
56534
+ unit: string().nullable(),
56535
+ min: number().nullable(),
56536
+ max: number().nullable(),
56537
+ step: number().nullable(),
56538
+ /** Allowed members of an enum; null for other types. */
56539
+ enumValues: array(string()).nullable(),
56540
+ defaultValue: DishwasherValueSchema.nullable()
56541
+ });
56542
+ var DishwasherProgramSchema = object({
56543
+ /** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
56544
+ key: string(),
56545
+ name: string(),
56546
+ /** The appliance currently offers this program. */
56547
+ available: boolean(),
56548
+ /** The options this program lists, with the program-level access / availability / default. */
56549
+ options: array(DishwasherOptionDescriptorSchema)
56550
+ });
56551
+ var DishwasherOptionsSchema = object({
56552
+ availability: DishwasherAvailabilitySchema,
56553
+ /** What the appliance can be told to do, from the commands its description declares. */
56554
+ supportsStart: boolean(),
56555
+ supportsPause: boolean(),
56556
+ supportsResume: boolean(),
56557
+ supportsStop: boolean(),
56558
+ supportsPower: boolean(),
56559
+ /** Every program the description lists, with its options. */
56560
+ programs: array(DishwasherProgramSchema),
56561
+ /** Every option and setting entity the description lists (programs reference these by key). */
56562
+ options: array(DishwasherOptionDescriptorSchema)
56563
+ });
56392
56564
  var dishwasherCapability = {
56393
56565
  name: "dishwasher",
56394
56566
  scope: "device",
@@ -56396,86 +56568,102 @@ var dishwasherCapability = {
56396
56568
  mode: "singleton",
56397
56569
  deviceTypes: [DeviceType.Dishwasher],
56398
56570
  methods: {
56399
- start: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56571
+ /**
56572
+ * Start a program. Without `program` the selected one starts. `options` are
56573
+ * option feature keys; each is checked against the program's constraints.
56574
+ */
56575
+ start: method(object({
56576
+ deviceId: DeviceIdSchema,
56577
+ program: string().min(1).optional(),
56578
+ options: record(string(), DishwasherValueSchema).optional()
56579
+ }), _void(), {
56400
56580
  kind: "mutation",
56401
56581
  auth: "protected"
56402
56582
  }),
56403
- pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56583
+ pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
56404
56584
  kind: "mutation",
56405
56585
  auth: "protected"
56406
56586
  }),
56407
- stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56587
+ resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
56588
+ kind: "mutation",
56589
+ auth: "protected"
56590
+ }),
56591
+ stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
56408
56592
  kind: "mutation",
56409
56593
  auth: "protected"
56410
56594
  }),
56595
+ /** Select (not start) a program; refused when the appliance does not offer it. */
56411
56596
  setProgram: method(object({
56412
- deviceId: number().int().nonnegative(),
56597
+ deviceId: DeviceIdSchema,
56413
56598
  program: string().min(1)
56414
56599
  }), _void(), {
56415
56600
  kind: "mutation",
56416
56601
  auth: "protected"
56417
56602
  }),
56418
56603
  setPower: method(object({
56419
- deviceId: number().int().nonnegative(),
56604
+ deviceId: DeviceIdSchema,
56420
56605
  on: boolean()
56421
56606
  }), _void(), {
56422
56607
  kind: "mutation",
56423
56608
  auth: "protected"
56424
56609
  }),
56425
56610
  setHalfLoad: method(object({
56426
- deviceId: number().int().nonnegative(),
56611
+ deviceId: DeviceIdSchema,
56427
56612
  on: boolean()
56428
56613
  }), _void(), {
56429
56614
  kind: "mutation",
56430
56615
  auth: "protected"
56431
56616
  }),
56432
56617
  setHygienePlus: method(object({
56433
- deviceId: number().int().nonnegative(),
56618
+ deviceId: DeviceIdSchema,
56434
56619
  on: boolean()
56435
56620
  }), _void(), {
56436
56621
  kind: "mutation",
56437
56622
  auth: "protected"
56438
56623
  }),
56439
56624
  setExtraDry: method(object({
56440
- deviceId: number().int().nonnegative(),
56625
+ deviceId: DeviceIdSchema,
56441
56626
  on: boolean()
56442
56627
  }), _void(), {
56443
56628
  kind: "mutation",
56444
56629
  auth: "protected"
56445
56630
  }),
56446
56631
  setIntensiveZone: method(object({
56447
- deviceId: number().int().nonnegative(),
56632
+ deviceId: DeviceIdSchema,
56448
56633
  on: boolean()
56449
56634
  }), _void(), {
56450
56635
  kind: "mutation",
56451
56636
  auth: "protected"
56452
56637
  }),
56453
56638
  setVarioSpeedPlus: method(object({
56454
- deviceId: number().int().nonnegative(),
56639
+ deviceId: DeviceIdSchema,
56455
56640
  on: boolean()
56456
56641
  }), _void(), {
56457
56642
  kind: "mutation",
56458
56643
  auth: "protected"
56459
56644
  }),
56460
56645
  setChildLock: method(object({
56461
- deviceId: number().int().nonnegative(),
56646
+ deviceId: DeviceIdSchema,
56462
56647
  on: boolean()
56463
56648
  }), _void(), {
56464
56649
  kind: "mutation",
56465
56650
  auth: "protected"
56466
56651
  }),
56652
+ /**
56653
+ * Write any option or setting by feature key. Refused when the description does
56654
+ * not list it, it is not writable or not available now, or the value is outside
56655
+ * its declared range / members.
56656
+ */
56467
56657
  setOption: method(object({
56468
- deviceId: number().int().nonnegative(),
56658
+ deviceId: DeviceIdSchema,
56469
56659
  key: string().min(1),
56470
- value: union([
56471
- boolean(),
56472
- string(),
56473
- number()
56474
- ])
56660
+ value: DishwasherValueSchema
56475
56661
  }), _void(), {
56476
56662
  kind: "mutation",
56477
56663
  auth: "protected"
56478
- })
56664
+ }),
56665
+ /** What this appliance can do, from its own description — the UI is derived from it. */
56666
+ getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
56479
56667
  },
56480
56668
  status: {
56481
56669
  schema: DishwasherStatusSchema,
@@ -70424,6 +70612,12 @@ Object.freeze({
70424
70612
  addonId: null,
70425
70613
  access: "view"
70426
70614
  },
70615
+ "dishwasher.getOptions": {
70616
+ capName: "dishwasher",
70617
+ capScope: "device",
70618
+ addonId: null,
70619
+ access: "view"
70620
+ },
70427
70621
  "dishwasher.getStatus": {
70428
70622
  capName: "dishwasher",
70429
70623
  capScope: "device",
@@ -70436,6 +70630,12 @@ Object.freeze({
70436
70630
  addonId: null,
70437
70631
  access: "create"
70438
70632
  },
70633
+ "dishwasher.resume": {
70634
+ capName: "dishwasher",
70635
+ capScope: "device",
70636
+ addonId: null,
70637
+ access: "create"
70638
+ },
70439
70639
  "dishwasher.setChildLock": {
70440
70640
  capName: "dishwasher",
70441
70641
  capScope: "device",
@@ -74936,6 +75136,12 @@ Object.freeze({
74936
75136
  addonId: null,
74937
75137
  access: "view"
74938
75138
  },
75139
+ "storageMigration.moverClearance": {
75140
+ capName: "storage-migration",
75141
+ capScope: "system",
75142
+ addonId: null,
75143
+ access: "view"
75144
+ },
74939
75145
  "storageMigration.movers": {
74940
75146
  capName: "storage-migration",
74941
75147
  capScope: "system",
@@ -77129,6 +77335,11 @@ Object.freeze({
77129
77335
  form: "single",
77130
77336
  optional: false
77131
77337
  }],
77338
+ "dishwasher.getOptions": [{
77339
+ name: "deviceId",
77340
+ form: "single",
77341
+ optional: false
77342
+ }],
77132
77343
  "dishwasher.getStatus": [{
77133
77344
  name: "deviceId",
77134
77345
  form: "single",
@@ -77139,6 +77350,11 @@ Object.freeze({
77139
77350
  form: "single",
77140
77351
  optional: false
77141
77352
  }],
77353
+ "dishwasher.resume": [{
77354
+ name: "deviceId",
77355
+ form: "single",
77356
+ optional: false
77357
+ }],
77142
77358
  "dishwasher.setChildLock": [{
77143
77359
  name: "deviceId",
77144
77360
  form: "single",
@@ -79225,6 +79441,9 @@ new Map(Object.entries({
79225
79441
  "wrapper-update-available": "system",
79226
79442
  "backup-completed": "system",
79227
79443
  "export-completed": "system",
79444
+ "alert-critical": "system",
79445
+ "alert-error": "system",
79446
+ "alert-critical-resolved": "system",
79228
79447
  "storage-location-low": "system",
79229
79448
  "storage-location-critical": "system",
79230
79449
  "storage-location-ok": "system",
@@ -79349,6 +79568,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79349
79568
  "storage-location-ok"
79350
79569
  ]
79351
79570
  },
79571
+ {
79572
+ id: "alerts",
79573
+ family: "system",
79574
+ label: "Alerts",
79575
+ kinds: [
79576
+ "alert-critical",
79577
+ "alert-error",
79578
+ "alert-critical-resolved"
79579
+ ]
79580
+ },
79352
79581
  {
79353
79582
  id: "alarm",
79354
79583
  family: "alarm",
@@ -79393,6 +79622,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
79393
79622
  return [[descriptor.kind, field]];
79394
79623
  })));
79395
79624
  Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
79625
+ object({
79626
+ phase: _enum(["raised", "resolved"]),
79627
+ episodeId: string().min(1),
79628
+ alertId: string().min(1),
79629
+ severity: AlertSeveritySchema,
79630
+ category: string(),
79631
+ title: string(),
79632
+ message: string(),
79633
+ sourceType: string().optional(),
79634
+ sourceId: string().optional(),
79635
+ nodeId: string().optional(),
79636
+ /** The alert's own action link (where the operator acts on it), when it has one. */
79637
+ actionUrl: string().optional(),
79638
+ at: number()
79639
+ });
79396
79640
  var RULE_BODY_ONLY = ["body"];
79397
79641
  var RULE_TEXT = ["title", "body"];
79398
79642
  var BATTERY = ["device-battery-low", "device-battery-normal"];
@@ -79402,6 +79646,11 @@ var TANK = [
79402
79646
  "device-tank-full",
79403
79647
  "device-tank-normal"
79404
79648
  ];
79649
+ var ALERT_EPISODE = [
79650
+ "alert-critical",
79651
+ "alert-error",
79652
+ "alert-critical-resolved"
79653
+ ];
79405
79654
  var UPDATES = [
79406
79655
  "addon-update-available",
79407
79656
  "server-update-available",
@@ -79594,14 +79843,14 @@ var STATE_SUMMARY_VARS = [
79594
79843
  ([...RULE_TEXT], [...CONSUMABLE]),
79595
79844
  ([...RULE_TEXT], [...TANK]),
79596
79845
  [...RULE_TEXT],
79597
- ([...RULE_TEXT], [...UPDATES]),
79598
- ([...RULE_TEXT], [...UPDATES]),
79599
- [...RULE_TEXT],
79846
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
79847
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
79600
79848
  [...RULE_TEXT],
79601
79849
  [...RULE_TEXT],
79602
79850
  [...RULE_TEXT],
79603
79851
  [...RULE_TEXT],
79604
79852
  [...RULE_TEXT],
79853
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79605
79854
  [...RULE_TEXT],
79606
79855
  [...RULE_TEXT],
79607
79856
  [...RULE_TEXT],
@@ -79619,7 +79868,11 @@ var STATE_SUMMARY_VARS = [
79619
79868
  [...RULE_TEXT],
79620
79869
  [...RULE_TEXT],
79621
79870
  [...RULE_TEXT],
79622
- [...RULE_TEXT],
79871
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79872
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79873
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79874
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79875
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79623
79876
  [...RULE_TEXT],
79624
79877
  [...RULE_TEXT],
79625
79878
  [...RULE_TEXT],