@camstack/addon-provider-amcrest 0.2.139 → 0.2.141

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.mjs CHANGED
@@ -14,7 +14,7 @@ import { networkInterfaces } from "node:os";
14
14
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
15
15
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
16
16
  //#endregion
17
- //#region ../types/dist/event-category-BvOFi6PY.mjs
17
+ //#region ../types/dist/event-category-DOl51-Ij.mjs
18
18
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
19
19
  EventCategory["SystemBoot"] = "system.boot";
20
20
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -93,9 +93,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
93
93
  /**
94
94
  * The node's one-shot runner boot check (D877): planned runners against the
95
95
  * process service, `degraded` when any is failed, refused or missing. The
96
- * alert centre turns it into one alert and a direct critical push.
96
+ * alert centre turns it into one critical alert.
97
97
  */
98
98
  EventCategory["SystemRunnerCheck"] = "system.runner-check";
99
+ /**
100
+ * An alert EPISODE opened or closed, emitted by the alert centre for alerts
101
+ * of severity `critical` or `error` (`AlertEpisodePayload`). The alert
102
+ * centre sends no notification of its own: Notification Center turns this
103
+ * into the `alert-critical` / `alert-error` / `alert-critical-resolved`
104
+ * system-event kinds, and reconciles from the alerts store because a bus
105
+ * event may be dropped (D8, D11).
106
+ */
107
+ EventCategory["AlertEpisode"] = "alert.episode";
99
108
  EventCategory["AddonError"] = "addon.error";
100
109
  EventCategory["AddonPageReady"] = "addon.page-ready";
101
110
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -5420,7 +5429,7 @@ var ZodIssueCode = {
5420
5429
  var ZodFirstPartyTypeKind;
5421
5430
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5422
5431
  //#endregion
5423
- //#region ../types/dist/sleep-BegKjwUu.mjs
5432
+ //#region ../types/dist/sleep-BxjU_fJM.mjs
5424
5433
  /**
5425
5434
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5426
5435
  * window to float samples (D455).
@@ -7802,6 +7811,12 @@ function normalizeAddonInitResult(result) {
7802
7811
  if (Array.isArray(result)) return { providers: result };
7803
7812
  return result;
7804
7813
  }
7814
+ /**
7815
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7816
+ * and validates them (`share-token.service.ts` builds its enum from this
7817
+ * list); a data plane names the kinds it ACCEPTS in `share`.
7818
+ */
7819
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7805
7820
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
7806
7821
  var PeerBytesTicketSchema = object({
7807
7822
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -12491,6 +12506,229 @@ var ConvertResultSchema = object({
12491
12506
  files: array(string()).readonly()
12492
12507
  })).readonly()
12493
12508
  });
12509
+ /**
12510
+ * Zod schemas for persisted record types.
12511
+ *
12512
+ * These schemas serve as the single source of truth for types that are
12513
+ * stored in the settings-store backend and retrieved via tRPC. They
12514
+ * replace the manual TypeScript interfaces with schema-derived types,
12515
+ * enabling runtime validation when reading from the backend.
12516
+ *
12517
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
12518
+ * keeps the original name for backward compatibility.
12519
+ */
12520
+ /**
12521
+ * Auth model (v2 — 2026-05-12 caps-only):
12522
+ *
12523
+ * Two principals:
12524
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
12525
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
12526
+ *
12527
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
12528
+ * `super_admin` — collapsed onto the single boolean because every
12529
+ * non-admin caller is governed by the same scope-check rules; the
12530
+ * distinction was only ever used to route role-specific procedures
12531
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12532
+ * with `isAdmin: false` + an explicit scope list.
12533
+ */
12534
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
12535
+ var MethodAccessSchema = _enum([
12536
+ "view",
12537
+ "create",
12538
+ "delete"
12539
+ ]);
12540
+ /**
12541
+ * A single scope grant. Three forms — checked in matcher with OR
12542
+ * semantics; the first match decides whether the call passes:
12543
+ *
12544
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
12545
+ * cap with the matching `scope` declaration. New caps inherit grants
12546
+ * automatically — adding a device cap to the codebase makes it
12547
+ * reachable to every user with `category:device [...]` without a
12548
+ * re-grant. Use this for "family viewer" / "operator" tiers.
12549
+ *
12550
+ * - `addon` — every cap that ships inside a given addon id. Niche;
12551
+ * useful when an integration needs to interact with one specific
12552
+ * addon's surface regardless of how many caps it exports.
12553
+ *
12554
+ * - `capability` — the most precise form. Single cap name. Use for
12555
+ * integration tokens where you want to grant `addons.installPackage`
12556
+ * and nothing else.
12557
+ *
12558
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
12559
+ * "give me everything" escape; there is no wildcard scope.
12560
+ */
12561
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
12562
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
12563
+ var CapScopeSchema = _enum(["device", "system"]);
12564
+ /**
12565
+ * DeviceSelector (scope model v3 — 2026-08-12).
12566
+ *
12567
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
12568
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
12569
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
12570
+ * AFTER the grant was minted — no re-grant, no re-login.
12571
+ *
12572
+ * - `all` — every device in the deployment. The broad viewer/operator
12573
+ * lever without a `category` grant (a `category` grant also covers device
12574
+ * caps that carry no deviceId; `all` is specifically the device set).
12575
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
12576
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
12577
+ * is NOT covered until the grant is edited.
12578
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
12579
+ * DYNAMIC. A device that changes type, or a new device of the type,
12580
+ * re-resolves on the next request.
12581
+ * - `locations` — every device whose operator-assigned `location` label is
12582
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
12583
+ * null/unset location matches NO `locations` selector.
12584
+ */
12585
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
12586
+ object({ kind: literal("all") }),
12587
+ object({
12588
+ kind: literal("ids"),
12589
+ ids: array(number().int()).min(1)
12590
+ }),
12591
+ object({
12592
+ kind: literal("types"),
12593
+ types: array(_enum(DeviceType)).min(1)
12594
+ }),
12595
+ object({
12596
+ kind: literal("locations"),
12597
+ locations: array(string().min(1)).min(1)
12598
+ })
12599
+ ]);
12600
+ var DeviceTokenScopeSchema = object({
12601
+ type: literal("device"),
12602
+ /** The device SET this grant covers — resolved against the live fleet. */
12603
+ selector: DeviceSelectorSchema,
12604
+ access: array(MethodAccessSchema).min(1),
12605
+ /**
12606
+ * Whether a grant on a PARENT device transparently covers its accessory
12607
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
12608
+ * Direction is parent → children ONLY.
12609
+ *
12610
+ * Absent → the matcher DERIVES it from the access flavour: `view`
12611
+ * inherits (a camera viewer sees the camera's accessories), `create` /
12612
+ * `delete` do NOT (actuating/removing a child is an explicit act the
12613
+ * operator must grant on the child, not inherit from the parent). Set it
12614
+ * explicitly to override that default per grant.
12615
+ */
12616
+ includeLinked: boolean().optional()
12617
+ });
12618
+ /**
12619
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
12620
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
12621
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
12622
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
12623
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
12624
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
12625
+ * migration cannot reach a JWT already in a client's hands; parse-time
12626
+ * migration covers both without a flag day. No cast — the raw object is read
12627
+ * through `Reflect.get` (its static type is `unknown`).
12628
+ */
12629
+ function migrateLegacyTokenScope(raw) {
12630
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
12631
+ if (Reflect.get(raw, "type") !== "device") return raw;
12632
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
12633
+ const targets = Reflect.get(raw, "targets");
12634
+ if (!Array.isArray(targets)) return raw;
12635
+ return {
12636
+ type: "device",
12637
+ selector: {
12638
+ kind: "ids",
12639
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
12640
+ },
12641
+ access: Reflect.get(raw, "access")
12642
+ };
12643
+ }
12644
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
12645
+ object({
12646
+ type: literal("category"),
12647
+ target: CapScopeSchema,
12648
+ access: array(MethodAccessSchema).min(1)
12649
+ }),
12650
+ object({
12651
+ type: literal("capability"),
12652
+ target: string(),
12653
+ access: array(MethodAccessSchema).min(1)
12654
+ }),
12655
+ object({
12656
+ type: literal("addon"),
12657
+ target: string(),
12658
+ access: array(MethodAccessSchema).min(1)
12659
+ }),
12660
+ DeviceTokenScopeSchema
12661
+ ]));
12662
+ object({
12663
+ id: string(),
12664
+ username: string(),
12665
+ passwordHash: string(),
12666
+ /**
12667
+ * Admin bypass. When true, the middleware skips the scope-access
12668
+ * check entirely. There is no other axis of privilege; the legacy
12669
+ * role enum collapsed onto this boolean in v2.
12670
+ */
12671
+ isAdmin: boolean().default(false),
12672
+ allowedProviders: AllowedProviderSchema,
12673
+ allowedDevices: AllowedDevicesSchema,
12674
+ /**
12675
+ * Scopes granted to this user. Admins bypass; their `scopes` is
12676
+ * ignored. Non-admins without scopes are locked out of every
12677
+ * protected call.
12678
+ */
12679
+ scopes: array(TokenScopeSchema).default([]),
12680
+ createdAt: number(),
12681
+ updatedAt: number()
12682
+ });
12683
+ object({
12684
+ id: string(),
12685
+ label: string(),
12686
+ isAdmin: boolean().default(false),
12687
+ allowedProviders: AllowedProviderSchema,
12688
+ allowedDevices: AllowedDevicesSchema,
12689
+ tokenHash: string(),
12690
+ tokenPrefix: string(),
12691
+ createdAt: number(),
12692
+ lastUsedAt: number().optional()
12693
+ });
12694
+ object({
12695
+ id: string(),
12696
+ userId: string(),
12697
+ name: string(),
12698
+ tokenHash: string(),
12699
+ tokenPrefix: string(),
12700
+ scopes: array(TokenScopeSchema),
12701
+ expiresAt: number().nullish(),
12702
+ lastUsedAt: number().nullish(),
12703
+ createdAt: number()
12704
+ });
12705
+ /** What a share-view grant lets its holder see. */
12706
+ var ShareViewGrantSchema = object({
12707
+ kind: _enum(SHARE_VIEW_KINDS),
12708
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
12709
+ /** Talk-back, opt-in at mint time; absent means off. */
12710
+ talk: boolean().optional()
12711
+ });
12712
+ var ShareViewScopeSchema = object({
12713
+ type: literal("share-view"),
12714
+ grant: ShareViewGrantSchema
12715
+ });
12716
+ var AddonRoutesScopeSchema = object({
12717
+ type: literal("addon-routes"),
12718
+ access: array(MethodAccessSchema).min(1)
12719
+ });
12720
+ var CredentialScopeSchema = union([
12721
+ literal("*"),
12722
+ ShareViewScopeSchema,
12723
+ AddonRoutesScopeSchema,
12724
+ TokenScopeSchema
12725
+ ]);
12726
+ object({
12727
+ kind: literal("credential"),
12728
+ sub: string().min(1),
12729
+ jti: string().min(16),
12730
+ scopes: array(CredentialScopeSchema).min(1)
12731
+ });
12494
12732
  _enum(["new-session", "step-up"]);
12495
12733
  /** The languages the hub's app landing pages are written in (D858). */
12496
12734
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -13207,7 +13445,14 @@ var AlertSeveritySchema = _enum([
13207
13445
  ]);
13208
13446
  var AlertActionSchema = object({
13209
13447
  label: string(),
13210
- href: string().optional()
13448
+ href: string().optional(),
13449
+ /**
13450
+ * How `href` is followed. Absent / `app`: an admin-ui route (client-side).
13451
+ * `server`: a route the HUB serves (an addon HTTP route such as an OAuth
13452
+ * start) — the browser must leave the SPA with a full navigation, because
13453
+ * the SPA has no such route and would bounce to the home page.
13454
+ */
13455
+ navigation: _enum(["app", "server"]).optional()
13211
13456
  });
13212
13457
  var AlertStatusSchema = _enum([
13213
13458
  "active",
@@ -42036,6 +42281,9 @@ var NcSystemEventKindSchema = _enum([
42036
42281
  "server-updated",
42037
42282
  "export-completed",
42038
42283
  "backup-completed",
42284
+ "alert-critical",
42285
+ "alert-error",
42286
+ "alert-critical-resolved",
42039
42287
  "camera-online",
42040
42288
  "camera-offline",
42041
42289
  "camera-disabled",
@@ -44071,202 +44319,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
44071
44319
  auth: "admin"
44072
44320
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
44073
44321
  /**
44074
- * Zod schemas for persisted record types.
44075
- *
44076
- * These schemas serve as the single source of truth for types that are
44077
- * stored in the settings-store backend and retrieved via tRPC. They
44078
- * replace the manual TypeScript interfaces with schema-derived types,
44079
- * enabling runtime validation when reading from the backend.
44080
- *
44081
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
44082
- * keeps the original name for backward compatibility.
44083
- */
44084
- /**
44085
- * Auth model (v2 — 2026-05-12 caps-only):
44086
- *
44087
- * Two principals:
44088
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
44089
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
44090
- *
44091
- * No role enum. There used to be `viewer / agent / scoped` and earlier
44092
- * `super_admin` — collapsed onto the single boolean because every
44093
- * non-admin caller is governed by the same scope-check rules; the
44094
- * distinction was only ever used to route role-specific procedures
44095
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
44096
- * with `isAdmin: false` + an explicit scope list.
44097
- */
44098
- /** Per-method access flavour. Materialised on every cap method via codegen. */
44099
- var MethodAccessSchema = _enum([
44100
- "view",
44101
- "create",
44102
- "delete"
44103
- ]);
44104
- /**
44105
- * A single scope grant. Three forms — checked in matcher with OR
44106
- * semantics; the first match decides whether the call passes:
44107
- *
44108
- * - `category` — broadest. `target: 'device' | 'system'` selects every
44109
- * cap with the matching `scope` declaration. New caps inherit grants
44110
- * automatically — adding a device cap to the codebase makes it
44111
- * reachable to every user with `category:device [...]` without a
44112
- * re-grant. Use this for "family viewer" / "operator" tiers.
44113
- *
44114
- * - `addon` — every cap that ships inside a given addon id. Niche;
44115
- * useful when an integration needs to interact with one specific
44116
- * addon's surface regardless of how many caps it exports.
44117
- *
44118
- * - `capability` — the most precise form. Single cap name. Use for
44119
- * integration tokens where you want to grant `addons.installPackage`
44120
- * and nothing else.
44121
- *
44122
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
44123
- * "give me everything" escape; there is no wildcard scope.
44124
- */
44125
- var AllowedProviderSchema = union([literal("*"), array(string())]);
44126
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
44127
- var CapScopeSchema = _enum(["device", "system"]);
44128
- /**
44129
- * DeviceSelector (scope model v3 — 2026-08-12).
44130
- *
44131
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
44132
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
44133
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
44134
- * AFTER the grant was minted — no re-grant, no re-login.
44135
- *
44136
- * - `all` — every device in the deployment. The broad viewer/operator
44137
- * lever without a `category` grant (a `category` grant also covers device
44138
- * caps that carry no deviceId; `all` is specifically the device set).
44139
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
44140
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
44141
- * is NOT covered until the grant is edited.
44142
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
44143
- * DYNAMIC. A device that changes type, or a new device of the type,
44144
- * re-resolves on the next request.
44145
- * - `locations` — every device whose operator-assigned `location` label is
44146
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
44147
- * null/unset location matches NO `locations` selector.
44148
- */
44149
- var DeviceSelectorSchema = discriminatedUnion("kind", [
44150
- object({ kind: literal("all") }),
44151
- object({
44152
- kind: literal("ids"),
44153
- ids: array(number().int()).min(1)
44154
- }),
44155
- object({
44156
- kind: literal("types"),
44157
- types: array(_enum(DeviceType)).min(1)
44158
- }),
44159
- object({
44160
- kind: literal("locations"),
44161
- locations: array(string().min(1)).min(1)
44162
- })
44163
- ]);
44164
- var DeviceTokenScopeSchema = object({
44165
- type: literal("device"),
44166
- /** The device SET this grant covers — resolved against the live fleet. */
44167
- selector: DeviceSelectorSchema,
44168
- access: array(MethodAccessSchema).min(1),
44169
- /**
44170
- * Whether a grant on a PARENT device transparently covers its accessory
44171
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
44172
- * Direction is parent → children ONLY.
44173
- *
44174
- * Absent → the matcher DERIVES it from the access flavour: `view`
44175
- * inherits (a camera viewer sees the camera's accessories), `create` /
44176
- * `delete` do NOT (actuating/removing a child is an explicit act the
44177
- * operator must grant on the child, not inherit from the parent). Set it
44178
- * explicitly to override that default per grant.
44179
- */
44180
- includeLinked: boolean().optional()
44181
- });
44182
- /**
44183
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
44184
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
44185
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
44186
- * EVERY parse path — stored records AND the JWT-carried scope arrays
44187
- * normalised at the request boundary ({@link normalizeTokenScopes} in
44188
- * `device-selector.ts`). Chosen over a one-time DB migration because a
44189
- * migration cannot reach a JWT already in a client's hands; parse-time
44190
- * migration covers both without a flag day. No cast — the raw object is read
44191
- * through `Reflect.get` (its static type is `unknown`).
44192
- */
44193
- function migrateLegacyTokenScope(raw) {
44194
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
44195
- if (Reflect.get(raw, "type") !== "device") return raw;
44196
- if (Reflect.get(raw, "selector") !== void 0) return raw;
44197
- const targets = Reflect.get(raw, "targets");
44198
- if (!Array.isArray(targets)) return raw;
44199
- return {
44200
- type: "device",
44201
- selector: {
44202
- kind: "ids",
44203
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
44204
- },
44205
- access: Reflect.get(raw, "access")
44206
- };
44207
- }
44208
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
44209
- object({
44210
- type: literal("category"),
44211
- target: CapScopeSchema,
44212
- access: array(MethodAccessSchema).min(1)
44213
- }),
44214
- object({
44215
- type: literal("capability"),
44216
- target: string(),
44217
- access: array(MethodAccessSchema).min(1)
44218
- }),
44219
- object({
44220
- type: literal("addon"),
44221
- target: string(),
44222
- access: array(MethodAccessSchema).min(1)
44223
- }),
44224
- DeviceTokenScopeSchema
44225
- ]));
44226
- object({
44227
- id: string(),
44228
- username: string(),
44229
- passwordHash: string(),
44230
- /**
44231
- * Admin bypass. When true, the middleware skips the scope-access
44232
- * check entirely. There is no other axis of privilege; the legacy
44233
- * role enum collapsed onto this boolean in v2.
44234
- */
44235
- isAdmin: boolean().default(false),
44236
- allowedProviders: AllowedProviderSchema,
44237
- allowedDevices: AllowedDevicesSchema,
44238
- /**
44239
- * Scopes granted to this user. Admins bypass; their `scopes` is
44240
- * ignored. Non-admins without scopes are locked out of every
44241
- * protected call.
44242
- */
44243
- scopes: array(TokenScopeSchema).default([]),
44244
- createdAt: number(),
44245
- updatedAt: number()
44246
- });
44247
- object({
44248
- id: string(),
44249
- label: string(),
44250
- isAdmin: boolean().default(false),
44251
- allowedProviders: AllowedProviderSchema,
44252
- allowedDevices: AllowedDevicesSchema,
44253
- tokenHash: string(),
44254
- tokenPrefix: string(),
44255
- createdAt: number(),
44256
- lastUsedAt: number().optional()
44257
- });
44258
- object({
44259
- id: string(),
44260
- userId: string(),
44261
- name: string(),
44262
- tokenHash: string(),
44263
- tokenPrefix: string(),
44264
- scopes: array(TokenScopeSchema),
44265
- expiresAt: number().nullish(),
44266
- lastUsedAt: number().nullish(),
44267
- createdAt: number()
44268
- });
44269
- /**
44270
44322
  * `oauth-integration` — a collection cap by which an addon declares
44271
44323
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
44272
44324
  * Each provider returns a static descriptor; the core enumerates them
@@ -51216,7 +51268,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
51216
51268
  }), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
51217
51269
  kind: "mutation",
51218
51270
  auth: "admin"
51219
- }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51271
+ }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
51272
+ clear: boolean(),
51273
+ repointLocationId: string().optional()
51274
+ }), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51220
51275
  kind: "mutation",
51221
51276
  auth: "admin"
51222
51277
  }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
@@ -55881,6 +55936,11 @@ onStatusChanged: { data: object({
55881
55936
  *
55882
55937
  * `kind: 'poll'` — cloud REST APIs typically have no push channel; the
55883
55938
  * provider refreshes the slice on an interval and eagerly after commands.
55939
+ *
55940
+ * UNKNOWN IS NOT OFF. Every field the appliance reports separately is
55941
+ * nullable: `null` means "not known right now" (the appliance has not said,
55942
+ * the link is down, or the description does not carry it) and is never
55943
+ * rendered or exported as `false` / `0`. `availability` says why.
55884
55944
  */
55885
55945
  var DishwasherStateSchema = _enum([
55886
55946
  "idle",
@@ -55890,43 +55950,155 @@ var DishwasherStateSchema = _enum([
55890
55950
  "error",
55891
55951
  "unavailable"
55892
55952
  ]);
55953
+ /**
55954
+ * The appliance's own operation state, uncollapsed. `state` above is the coarse
55955
+ * view for compact surfaces; this is what the appliance said.
55956
+ */
55957
+ var DishwasherOperationStateSchema = _enum([
55958
+ "Inactive",
55959
+ "Ready",
55960
+ "DelayedStart",
55961
+ "Run",
55962
+ "Pause",
55963
+ "ActionRequired",
55964
+ "Finished",
55965
+ "Error",
55966
+ "Aborting"
55967
+ ]);
55968
+ /**
55969
+ * Why fields may be `null`:
55970
+ * - `available` — the link is up and the description is loaded;
55971
+ * - `offline` — the local link is down (values are unknown, not last-known);
55972
+ * - `description-missing` — the link is up but the appliance's description could not
55973
+ * be loaded, so its values cannot be decoded.
55974
+ */
55975
+ var DishwasherAvailabilitySchema = _enum([
55976
+ "available",
55977
+ "offline",
55978
+ "description-missing"
55979
+ ]);
55893
55980
  var DishwasherConsumableLevelSchema = _enum([
55894
55981
  "ok",
55895
55982
  "low",
55896
55983
  "empty"
55897
55984
  ]);
55898
55985
  var DishwasherStatusSchema = object({
55986
+ availability: DishwasherAvailabilitySchema,
55987
+ /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
55899
55988
  state: DishwasherStateSchema,
55900
- /** Active program id/name, or null when none selected / unknown. */
55989
+ /** The appliance's operation state as reported; null when not known. */
55990
+ operationState: DishwasherOperationStateSchema.nullable(),
55991
+ /** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
55901
55992
  program: string().nullable(),
55902
- /** Program tokens the hardware accepts — drives the UI selector. */
55993
+ /** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
55994
+ selectedProgram: string().nullable(),
55995
+ /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
55903
55996
  availablePrograms: array(string()),
55904
- /** Minutes remaining on the active cycle, or null when not running. */
55905
- remainingMinutes: number().int().nonnegative().nullable(),
55997
+ /** Seconds remaining on the active cycle, or null when not running / not known. */
55998
+ remainingSeconds: number().int().nonnegative().nullable(),
55999
+ /** Seconds the delayed start is set to (time until the cycle starts), or null. */
56000
+ delayedStartSeconds: number().int().nonnegative().nullable(),
55906
56001
  /** Cycle completion 0..100, or null when not applicable. */
55907
56002
  progressPercent: number().min(0).max(100).nullable(),
55908
- /** True when the door is reported open. */
55909
- doorOpen: boolean(),
55910
- /** True when remote start is allowed (door closed, power on, etc.). */
55911
- remoteStartAllowed: boolean(),
55912
- /** Main power / switched-on state. */
55913
- powerOn: boolean(),
56003
+ /** True when the door is reported open; null when the door state is not known. */
56004
+ doorOpen: boolean().nullable(),
56005
+ /** True when the door is latched (locked) during a cycle; null when not reported. */
56006
+ doorLocked: boolean().nullable(),
56007
+ /** True when remote start is allowed (door closed, power on, etc.); null when not known. */
56008
+ remoteStartAllowed: boolean().nullable(),
56009
+ /** True when the appliance accepts remote control now; null when not known. */
56010
+ remoteControlActive: boolean().nullable(),
56011
+ /** True while somebody operates the appliance at its panel; null when not reported. */
56012
+ localControlActive: boolean().nullable(),
56013
+ /** Main power / switched-on state; null when not known. */
56014
+ powerOn: boolean().nullable(),
56015
+ /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56016
+ powerState: string().nullable(),
55914
56017
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
55915
56018
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55916
- halfLoad: boolean(),
55917
- hygienePlus: boolean(),
56019
+ /** Option states: null when the appliance does not expose the option or has not said. */
56020
+ halfLoad: boolean().nullable(),
56021
+ hygienePlus: boolean().nullable(),
55918
56022
  /** Extra dry option when the appliance exposes it. */
55919
- extraDry: boolean(),
56023
+ extraDry: boolean().nullable(),
55920
56024
  /** Intensive zone (lower basket) when the appliance exposes it. */
55921
- intensiveZone: boolean(),
56025
+ intensiveZone: boolean().nullable(),
55922
56026
  /** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
55923
- varioSpeedPlus: boolean(),
55924
- /** Child lock (controls disabled on the appliance). */
55925
- childLock: boolean(),
56027
+ varioSpeedPlus: boolean().nullable(),
56028
+ /** Child lock (controls disabled on the appliance); null when not known. */
56029
+ childLock: boolean().nullable(),
56030
+ /** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
56031
+ activeEvents: array(string()),
56032
+ /** Numeric error code when the appliance reports one; null otherwise. */
55926
56033
  errorCode: number().nullable(),
56034
+ /** Name of the raised alert-level event while the appliance is in error; null otherwise. */
55927
56035
  errorLabel: string().nullable(),
56036
+ /** Ms epoch of the last value received from the appliance; 0 = never. */
55928
56037
  lastFetchedAt: number()
55929
56038
  });
56039
+ var DeviceIdSchema = number().int().nonnegative();
56040
+ /** A value a program option or setting can take. */
56041
+ var DishwasherValueSchema = union([
56042
+ boolean(),
56043
+ string(),
56044
+ number()
56045
+ ]);
56046
+ var DishwasherAccessSchema = _enum([
56047
+ "none",
56048
+ "read",
56049
+ "readWrite",
56050
+ "writeOnly",
56051
+ "readStatic"
56052
+ ]);
56053
+ /**
56054
+ * One option or setting the appliance declares, with the constraints its description
56055
+ * gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
56056
+ */
56057
+ var DishwasherOptionDescriptorSchema = object({
56058
+ /** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
56059
+ key: string(),
56060
+ /** Last segment of the key, for display. */
56061
+ name: string(),
56062
+ type: _enum([
56063
+ "boolean",
56064
+ "number",
56065
+ "enum",
56066
+ "string"
56067
+ ]),
56068
+ access: DishwasherAccessSchema,
56069
+ /** The appliance reports this entity as currently available. */
56070
+ available: boolean(),
56071
+ /** Unit the description declares for a number; null when it declares none. */
56072
+ unit: string().nullable(),
56073
+ min: number().nullable(),
56074
+ max: number().nullable(),
56075
+ step: number().nullable(),
56076
+ /** Allowed members of an enum; null for other types. */
56077
+ enumValues: array(string()).nullable(),
56078
+ defaultValue: DishwasherValueSchema.nullable()
56079
+ });
56080
+ var DishwasherProgramSchema = object({
56081
+ /** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
56082
+ key: string(),
56083
+ name: string(),
56084
+ /** The appliance currently offers this program. */
56085
+ available: boolean(),
56086
+ /** The options this program lists, with the program-level access / availability / default. */
56087
+ options: array(DishwasherOptionDescriptorSchema)
56088
+ });
56089
+ var DishwasherOptionsSchema = object({
56090
+ availability: DishwasherAvailabilitySchema,
56091
+ /** What the appliance can be told to do, from the commands its description declares. */
56092
+ supportsStart: boolean(),
56093
+ supportsPause: boolean(),
56094
+ supportsResume: boolean(),
56095
+ supportsStop: boolean(),
56096
+ supportsPower: boolean(),
56097
+ /** Every program the description lists, with its options. */
56098
+ programs: array(DishwasherProgramSchema),
56099
+ /** Every option and setting entity the description lists (programs reference these by key). */
56100
+ options: array(DishwasherOptionDescriptorSchema)
56101
+ });
55930
56102
  var dishwasherCapability = {
55931
56103
  name: "dishwasher",
55932
56104
  scope: "device",
@@ -55934,86 +56106,102 @@ var dishwasherCapability = {
55934
56106
  mode: "singleton",
55935
56107
  deviceTypes: [DeviceType.Dishwasher],
55936
56108
  methods: {
55937
- start: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56109
+ /**
56110
+ * Start a program. Without `program` the selected one starts. `options` are
56111
+ * option feature keys; each is checked against the program's constraints.
56112
+ */
56113
+ start: method(object({
56114
+ deviceId: DeviceIdSchema,
56115
+ program: string().min(1).optional(),
56116
+ options: record(string(), DishwasherValueSchema).optional()
56117
+ }), _void(), {
55938
56118
  kind: "mutation",
55939
56119
  auth: "protected"
55940
56120
  }),
55941
- pause: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56121
+ pause: method(object({ deviceId: DeviceIdSchema }), _void(), {
55942
56122
  kind: "mutation",
55943
56123
  auth: "protected"
55944
56124
  }),
55945
- stop: method(object({ deviceId: number().int().nonnegative() }), _void(), {
56125
+ resume: method(object({ deviceId: DeviceIdSchema }), _void(), {
56126
+ kind: "mutation",
56127
+ auth: "protected"
56128
+ }),
56129
+ stop: method(object({ deviceId: DeviceIdSchema }), _void(), {
55946
56130
  kind: "mutation",
55947
56131
  auth: "protected"
55948
56132
  }),
56133
+ /** Select (not start) a program; refused when the appliance does not offer it. */
55949
56134
  setProgram: method(object({
55950
- deviceId: number().int().nonnegative(),
56135
+ deviceId: DeviceIdSchema,
55951
56136
  program: string().min(1)
55952
56137
  }), _void(), {
55953
56138
  kind: "mutation",
55954
56139
  auth: "protected"
55955
56140
  }),
55956
56141
  setPower: method(object({
55957
- deviceId: number().int().nonnegative(),
56142
+ deviceId: DeviceIdSchema,
55958
56143
  on: boolean()
55959
56144
  }), _void(), {
55960
56145
  kind: "mutation",
55961
56146
  auth: "protected"
55962
56147
  }),
55963
56148
  setHalfLoad: method(object({
55964
- deviceId: number().int().nonnegative(),
56149
+ deviceId: DeviceIdSchema,
55965
56150
  on: boolean()
55966
56151
  }), _void(), {
55967
56152
  kind: "mutation",
55968
56153
  auth: "protected"
55969
56154
  }),
55970
56155
  setHygienePlus: method(object({
55971
- deviceId: number().int().nonnegative(),
56156
+ deviceId: DeviceIdSchema,
55972
56157
  on: boolean()
55973
56158
  }), _void(), {
55974
56159
  kind: "mutation",
55975
56160
  auth: "protected"
55976
56161
  }),
55977
56162
  setExtraDry: method(object({
55978
- deviceId: number().int().nonnegative(),
56163
+ deviceId: DeviceIdSchema,
55979
56164
  on: boolean()
55980
56165
  }), _void(), {
55981
56166
  kind: "mutation",
55982
56167
  auth: "protected"
55983
56168
  }),
55984
56169
  setIntensiveZone: method(object({
55985
- deviceId: number().int().nonnegative(),
56170
+ deviceId: DeviceIdSchema,
55986
56171
  on: boolean()
55987
56172
  }), _void(), {
55988
56173
  kind: "mutation",
55989
56174
  auth: "protected"
55990
56175
  }),
55991
56176
  setVarioSpeedPlus: method(object({
55992
- deviceId: number().int().nonnegative(),
56177
+ deviceId: DeviceIdSchema,
55993
56178
  on: boolean()
55994
56179
  }), _void(), {
55995
56180
  kind: "mutation",
55996
56181
  auth: "protected"
55997
56182
  }),
55998
56183
  setChildLock: method(object({
55999
- deviceId: number().int().nonnegative(),
56184
+ deviceId: DeviceIdSchema,
56000
56185
  on: boolean()
56001
56186
  }), _void(), {
56002
56187
  kind: "mutation",
56003
56188
  auth: "protected"
56004
56189
  }),
56190
+ /**
56191
+ * Write any option or setting by feature key. Refused when the description does
56192
+ * not list it, it is not writable or not available now, or the value is outside
56193
+ * its declared range / members.
56194
+ */
56005
56195
  setOption: method(object({
56006
- deviceId: number().int().nonnegative(),
56196
+ deviceId: DeviceIdSchema,
56007
56197
  key: string().min(1),
56008
- value: union([
56009
- boolean(),
56010
- string(),
56011
- number()
56012
- ])
56198
+ value: DishwasherValueSchema
56013
56199
  }), _void(), {
56014
56200
  kind: "mutation",
56015
56201
  auth: "protected"
56016
- })
56202
+ }),
56203
+ /** What this appliance can do, from its own description — the UI is derived from it. */
56204
+ getOptions: method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
56017
56205
  },
56018
56206
  status: {
56019
56207
  schema: DishwasherStatusSchema,
@@ -70428,6 +70616,12 @@ Object.freeze({
70428
70616
  addonId: null,
70429
70617
  access: "view"
70430
70618
  },
70619
+ "dishwasher.getOptions": {
70620
+ capName: "dishwasher",
70621
+ capScope: "device",
70622
+ addonId: null,
70623
+ access: "view"
70624
+ },
70431
70625
  "dishwasher.getStatus": {
70432
70626
  capName: "dishwasher",
70433
70627
  capScope: "device",
@@ -70440,6 +70634,12 @@ Object.freeze({
70440
70634
  addonId: null,
70441
70635
  access: "create"
70442
70636
  },
70637
+ "dishwasher.resume": {
70638
+ capName: "dishwasher",
70639
+ capScope: "device",
70640
+ addonId: null,
70641
+ access: "create"
70642
+ },
70443
70643
  "dishwasher.setChildLock": {
70444
70644
  capName: "dishwasher",
70445
70645
  capScope: "device",
@@ -74940,6 +75140,12 @@ Object.freeze({
74940
75140
  addonId: null,
74941
75141
  access: "view"
74942
75142
  },
75143
+ "storageMigration.moverClearance": {
75144
+ capName: "storage-migration",
75145
+ capScope: "system",
75146
+ addonId: null,
75147
+ access: "view"
75148
+ },
74943
75149
  "storageMigration.movers": {
74944
75150
  capName: "storage-migration",
74945
75151
  capScope: "system",
@@ -77339,6 +77545,11 @@ Object.freeze({
77339
77545
  form: "single",
77340
77546
  optional: false
77341
77547
  }],
77548
+ "dishwasher.getOptions": [{
77549
+ name: "deviceId",
77550
+ form: "single",
77551
+ optional: false
77552
+ }],
77342
77553
  "dishwasher.getStatus": [{
77343
77554
  name: "deviceId",
77344
77555
  form: "single",
@@ -77349,6 +77560,11 @@ Object.freeze({
77349
77560
  form: "single",
77350
77561
  optional: false
77351
77562
  }],
77563
+ "dishwasher.resume": [{
77564
+ name: "deviceId",
77565
+ form: "single",
77566
+ optional: false
77567
+ }],
77352
77568
  "dishwasher.setChildLock": [{
77353
77569
  name: "deviceId",
77354
77570
  form: "single",
@@ -79435,6 +79651,9 @@ new Map(Object.entries({
79435
79651
  "wrapper-update-available": "system",
79436
79652
  "backup-completed": "system",
79437
79653
  "export-completed": "system",
79654
+ "alert-critical": "system",
79655
+ "alert-error": "system",
79656
+ "alert-critical-resolved": "system",
79438
79657
  "storage-location-low": "system",
79439
79658
  "storage-location-critical": "system",
79440
79659
  "storage-location-ok": "system",
@@ -79559,6 +79778,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79559
79778
  "storage-location-ok"
79560
79779
  ]
79561
79780
  },
79781
+ {
79782
+ id: "alerts",
79783
+ family: "system",
79784
+ label: "Alerts",
79785
+ kinds: [
79786
+ "alert-critical",
79787
+ "alert-error",
79788
+ "alert-critical-resolved"
79789
+ ]
79790
+ },
79562
79791
  {
79563
79792
  id: "alarm",
79564
79793
  family: "alarm",
@@ -79603,6 +79832,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
79603
79832
  return [[descriptor.kind, field]];
79604
79833
  })));
79605
79834
  Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
79835
+ object({
79836
+ phase: _enum(["raised", "resolved"]),
79837
+ episodeId: string().min(1),
79838
+ alertId: string().min(1),
79839
+ severity: AlertSeveritySchema,
79840
+ category: string(),
79841
+ title: string(),
79842
+ message: string(),
79843
+ sourceType: string().optional(),
79844
+ sourceId: string().optional(),
79845
+ nodeId: string().optional(),
79846
+ /** The alert's own action link (where the operator acts on it), when it has one. */
79847
+ actionUrl: string().optional(),
79848
+ at: number()
79849
+ });
79606
79850
  var RULE_BODY_ONLY = ["body"];
79607
79851
  var RULE_TEXT = ["title", "body"];
79608
79852
  var BATTERY = ["device-battery-low", "device-battery-normal"];
@@ -79612,6 +79856,11 @@ var TANK = [
79612
79856
  "device-tank-full",
79613
79857
  "device-tank-normal"
79614
79858
  ];
79859
+ var ALERT_EPISODE = [
79860
+ "alert-critical",
79861
+ "alert-error",
79862
+ "alert-critical-resolved"
79863
+ ];
79615
79864
  var UPDATES = [
79616
79865
  "addon-update-available",
79617
79866
  "server-update-available",
@@ -79804,14 +80053,14 @@ var STATE_SUMMARY_VARS = [
79804
80053
  ([...RULE_TEXT], [...CONSUMABLE]),
79805
80054
  ([...RULE_TEXT], [...TANK]),
79806
80055
  [...RULE_TEXT],
79807
- ([...RULE_TEXT], [...UPDATES]),
79808
- ([...RULE_TEXT], [...UPDATES]),
79809
- [...RULE_TEXT],
80056
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
80057
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
79810
80058
  [...RULE_TEXT],
79811
80059
  [...RULE_TEXT],
79812
80060
  [...RULE_TEXT],
79813
80061
  [...RULE_TEXT],
79814
80062
  [...RULE_TEXT],
80063
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79815
80064
  [...RULE_TEXT],
79816
80065
  [...RULE_TEXT],
79817
80066
  [...RULE_TEXT],
@@ -79829,7 +80078,11 @@ var STATE_SUMMARY_VARS = [
79829
80078
  [...RULE_TEXT],
79830
80079
  [...RULE_TEXT],
79831
80080
  [...RULE_TEXT],
79832
- [...RULE_TEXT],
80081
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
80082
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
80083
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
80084
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
80085
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
79833
80086
  [...RULE_TEXT],
79834
80087
  [...RULE_TEXT],
79835
80088
  [...RULE_TEXT],