@camstack/addon-model-studio 1.1.271 → 1.1.273

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 (18) hide show
  1. package/dist/{MotionZonesSettings-DzJf18cG.mjs → MotionZonesSettings-Duuc8czf.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-BfcxIzcV.mjs → PrivacyMaskSettings-WF3MWogd.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-CXZ7rmkI.mjs → SceneMonitorEditor-qLV4EW0B.mjs} +3 -3
  4. package/dist/_stub.js +2592 -2543
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-C6bgtko3.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-j0yqR-LS.mjs} +4 -4
  6. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Z7ZkM51W.mjs +26 -0
  7. package/dist/{hostInit-CXCV1rE1.mjs → hostInit-Cq_rzz4M.mjs} +3 -3
  8. package/dist/model-studio.addon.js +480 -240
  9. package/dist/model-studio.addon.mjs +480 -240
  10. package/dist/{player-overlays-mDdhIu2Z.mjs → player-overlays-CT6XuXiM.mjs} +1 -1
  11. package/dist/remoteEntry.js +1 -1
  12. package/dist/{responsive-BDYhKoco.mjs → responsive-CYduFr5C.mjs} +1 -1
  13. package/dist/{scene-monitor-copy-CqHEekjf.mjs → scene-monitor-copy-CPlDlbF7.mjs} +1 -1
  14. package/dist/{square-Br-2YTir.mjs → square-CDQOHhX3.mjs} +1 -1
  15. package/dist/{trash-2-Dyh-Oss-.mjs → trash-2-CHBNgRI-.mjs} +1 -1
  16. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-uFBENbsJ.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CoBHAIAZ.mjs} +1 -1
  17. package/package.json +1 -1
  18. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BpItLART.mjs +0 -26
@@ -394,7 +394,7 @@ function buildScryptedRegistryDescriptor(entry) {
394
394
  };
395
395
  }
396
396
  //#endregion
397
- //#region ../types/dist/event-category-BvOFi6PY.mjs
397
+ //#region ../types/dist/event-category-DOl51-Ij.mjs
398
398
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
399
399
  EventCategory["SystemBoot"] = "system.boot";
400
400
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -473,9 +473,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
473
473
  /**
474
474
  * The node's one-shot runner boot check (D877): planned runners against the
475
475
  * process service, `degraded` when any is failed, refused or missing. The
476
- * alert centre turns it into one alert and a direct critical push.
476
+ * alert centre turns it into one critical alert.
477
477
  */
478
478
  EventCategory["SystemRunnerCheck"] = "system.runner-check";
479
+ /**
480
+ * An alert EPISODE opened or closed, emitted by the alert centre for alerts
481
+ * of severity `critical` or `error` (`AlertEpisodePayload`). The alert
482
+ * centre sends no notification of its own: Notification Center turns this
483
+ * into the `alert-critical` / `alert-error` / `alert-critical-resolved`
484
+ * system-event kinds, and reconciles from the alerts store because a bus
485
+ * event may be dropped (D8, D11).
486
+ */
487
+ EventCategory["AlertEpisode"] = "alert.episode";
479
488
  EventCategory["AddonError"] = "addon.error";
480
489
  EventCategory["AddonPageReady"] = "addon.page-ready";
481
490
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -5800,7 +5809,7 @@ var ZodIssueCode = {
5800
5809
  var ZodFirstPartyTypeKind;
5801
5810
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5802
5811
  //#endregion
5803
- //#region ../types/dist/sleep-BegKjwUu.mjs
5812
+ //#region ../types/dist/sleep-BxjU_fJM.mjs
5804
5813
  /**
5805
5814
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5806
5815
  * window to float samples (D455).
@@ -8182,6 +8191,12 @@ function normalizeAddonInitResult(result) {
8182
8191
  if (Array.isArray(result)) return { providers: result };
8183
8192
  return result;
8184
8193
  }
8194
+ /**
8195
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
8196
+ * and validates them (`share-token.service.ts` builds its enum from this
8197
+ * list); a data plane names the kinds it ACCEPTS in `share`.
8198
+ */
8199
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
8185
8200
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
8186
8201
  var PeerBytesTicketSchema = object({
8187
8202
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -12986,6 +13001,229 @@ var ConvertResultSchema = object({
12986
13001
  entry: ModelCatalogEntrySchema,
12987
13002
  artifacts: array(ConvertArtifactSchema).readonly()
12988
13003
  });
13004
+ /**
13005
+ * Zod schemas for persisted record types.
13006
+ *
13007
+ * These schemas serve as the single source of truth for types that are
13008
+ * stored in the settings-store backend and retrieved via tRPC. They
13009
+ * replace the manual TypeScript interfaces with schema-derived types,
13010
+ * enabling runtime validation when reading from the backend.
13011
+ *
13012
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
13013
+ * keeps the original name for backward compatibility.
13014
+ */
13015
+ /**
13016
+ * Auth model (v2 — 2026-05-12 caps-only):
13017
+ *
13018
+ * Two principals:
13019
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
13020
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
13021
+ *
13022
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
13023
+ * `super_admin` — collapsed onto the single boolean because every
13024
+ * non-admin caller is governed by the same scope-check rules; the
13025
+ * distinction was only ever used to route role-specific procedures
13026
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
13027
+ * with `isAdmin: false` + an explicit scope list.
13028
+ */
13029
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
13030
+ var MethodAccessSchema = _enum([
13031
+ "view",
13032
+ "create",
13033
+ "delete"
13034
+ ]);
13035
+ /**
13036
+ * A single scope grant. Three forms — checked in matcher with OR
13037
+ * semantics; the first match decides whether the call passes:
13038
+ *
13039
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
13040
+ * cap with the matching `scope` declaration. New caps inherit grants
13041
+ * automatically — adding a device cap to the codebase makes it
13042
+ * reachable to every user with `category:device [...]` without a
13043
+ * re-grant. Use this for "family viewer" / "operator" tiers.
13044
+ *
13045
+ * - `addon` — every cap that ships inside a given addon id. Niche;
13046
+ * useful when an integration needs to interact with one specific
13047
+ * addon's surface regardless of how many caps it exports.
13048
+ *
13049
+ * - `capability` — the most precise form. Single cap name. Use for
13050
+ * integration tokens where you want to grant `addons.installPackage`
13051
+ * and nothing else.
13052
+ *
13053
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
13054
+ * "give me everything" escape; there is no wildcard scope.
13055
+ */
13056
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
13057
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
13058
+ var CapScopeSchema = _enum(["device", "system"]);
13059
+ /**
13060
+ * DeviceSelector (scope model v3 — 2026-08-12).
13061
+ *
13062
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
13063
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
13064
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
13065
+ * AFTER the grant was minted — no re-grant, no re-login.
13066
+ *
13067
+ * - `all` — every device in the deployment. The broad viewer/operator
13068
+ * lever without a `category` grant (a `category` grant also covers device
13069
+ * caps that carry no deviceId; `all` is specifically the device set).
13070
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
13071
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
13072
+ * is NOT covered until the grant is edited.
13073
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
13074
+ * DYNAMIC. A device that changes type, or a new device of the type,
13075
+ * re-resolves on the next request.
13076
+ * - `locations` — every device whose operator-assigned `location` label is
13077
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
13078
+ * null/unset location matches NO `locations` selector.
13079
+ */
13080
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
13081
+ object({ kind: literal("all") }),
13082
+ object({
13083
+ kind: literal("ids"),
13084
+ ids: array(number().int()).min(1)
13085
+ }),
13086
+ object({
13087
+ kind: literal("types"),
13088
+ types: array(_enum(DeviceType)).min(1)
13089
+ }),
13090
+ object({
13091
+ kind: literal("locations"),
13092
+ locations: array(string().min(1)).min(1)
13093
+ })
13094
+ ]);
13095
+ var DeviceTokenScopeSchema = object({
13096
+ type: literal("device"),
13097
+ /** The device SET this grant covers — resolved against the live fleet. */
13098
+ selector: DeviceSelectorSchema,
13099
+ access: array(MethodAccessSchema).min(1),
13100
+ /**
13101
+ * Whether a grant on a PARENT device transparently covers its accessory
13102
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
13103
+ * Direction is parent → children ONLY.
13104
+ *
13105
+ * Absent → the matcher DERIVES it from the access flavour: `view`
13106
+ * inherits (a camera viewer sees the camera's accessories), `create` /
13107
+ * `delete` do NOT (actuating/removing a child is an explicit act the
13108
+ * operator must grant on the child, not inherit from the parent). Set it
13109
+ * explicitly to override that default per grant.
13110
+ */
13111
+ includeLinked: boolean().optional()
13112
+ });
13113
+ /**
13114
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
13115
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
13116
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
13117
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
13118
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
13119
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
13120
+ * migration cannot reach a JWT already in a client's hands; parse-time
13121
+ * migration covers both without a flag day. No cast — the raw object is read
13122
+ * through `Reflect.get` (its static type is `unknown`).
13123
+ */
13124
+ function migrateLegacyTokenScope(raw) {
13125
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
13126
+ if (Reflect.get(raw, "type") !== "device") return raw;
13127
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
13128
+ const targets = Reflect.get(raw, "targets");
13129
+ if (!Array.isArray(targets)) return raw;
13130
+ return {
13131
+ type: "device",
13132
+ selector: {
13133
+ kind: "ids",
13134
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
13135
+ },
13136
+ access: Reflect.get(raw, "access")
13137
+ };
13138
+ }
13139
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
13140
+ object({
13141
+ type: literal("category"),
13142
+ target: CapScopeSchema,
13143
+ access: array(MethodAccessSchema).min(1)
13144
+ }),
13145
+ object({
13146
+ type: literal("capability"),
13147
+ target: string(),
13148
+ access: array(MethodAccessSchema).min(1)
13149
+ }),
13150
+ object({
13151
+ type: literal("addon"),
13152
+ target: string(),
13153
+ access: array(MethodAccessSchema).min(1)
13154
+ }),
13155
+ DeviceTokenScopeSchema
13156
+ ]));
13157
+ object({
13158
+ id: string(),
13159
+ username: string(),
13160
+ passwordHash: string(),
13161
+ /**
13162
+ * Admin bypass. When true, the middleware skips the scope-access
13163
+ * check entirely. There is no other axis of privilege; the legacy
13164
+ * role enum collapsed onto this boolean in v2.
13165
+ */
13166
+ isAdmin: boolean().default(false),
13167
+ allowedProviders: AllowedProviderSchema,
13168
+ allowedDevices: AllowedDevicesSchema,
13169
+ /**
13170
+ * Scopes granted to this user. Admins bypass; their `scopes` is
13171
+ * ignored. Non-admins without scopes are locked out of every
13172
+ * protected call.
13173
+ */
13174
+ scopes: array(TokenScopeSchema).default([]),
13175
+ createdAt: number(),
13176
+ updatedAt: number()
13177
+ });
13178
+ object({
13179
+ id: string(),
13180
+ label: string(),
13181
+ isAdmin: boolean().default(false),
13182
+ allowedProviders: AllowedProviderSchema,
13183
+ allowedDevices: AllowedDevicesSchema,
13184
+ tokenHash: string(),
13185
+ tokenPrefix: string(),
13186
+ createdAt: number(),
13187
+ lastUsedAt: number().optional()
13188
+ });
13189
+ object({
13190
+ id: string(),
13191
+ userId: string(),
13192
+ name: string(),
13193
+ tokenHash: string(),
13194
+ tokenPrefix: string(),
13195
+ scopes: array(TokenScopeSchema),
13196
+ expiresAt: number().nullish(),
13197
+ lastUsedAt: number().nullish(),
13198
+ createdAt: number()
13199
+ });
13200
+ /** What a share-view grant lets its holder see. */
13201
+ var ShareViewGrantSchema = object({
13202
+ kind: _enum(SHARE_VIEW_KINDS),
13203
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
13204
+ /** Talk-back, opt-in at mint time; absent means off. */
13205
+ talk: boolean().optional()
13206
+ });
13207
+ var ShareViewScopeSchema = object({
13208
+ type: literal("share-view"),
13209
+ grant: ShareViewGrantSchema
13210
+ });
13211
+ var AddonRoutesScopeSchema = object({
13212
+ type: literal("addon-routes"),
13213
+ access: array(MethodAccessSchema).min(1)
13214
+ });
13215
+ var CredentialScopeSchema = union([
13216
+ literal("*"),
13217
+ ShareViewScopeSchema,
13218
+ AddonRoutesScopeSchema,
13219
+ TokenScopeSchema
13220
+ ]);
13221
+ object({
13222
+ kind: literal("credential"),
13223
+ sub: string().min(1),
13224
+ jti: string().min(16),
13225
+ scopes: array(CredentialScopeSchema).min(1)
13226
+ });
12989
13227
  _enum(["new-session", "step-up"]);
12990
13228
  /** The languages the hub's app landing pages are written in (D858). */
12991
13229
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -13719,7 +13957,14 @@ var AlertSeveritySchema = _enum([
13719
13957
  ]);
13720
13958
  var AlertActionSchema = object({
13721
13959
  label: string(),
13722
- href: string().optional()
13960
+ href: string().optional(),
13961
+ /**
13962
+ * How `href` is followed. Absent / `app`: an admin-ui route (client-side).
13963
+ * `server`: a route the HUB serves (an addon HTTP route such as an OAuth
13964
+ * start) — the browser must leave the SPA with a full navigation, because
13965
+ * the SPA has no such route and would bounce to the home page.
13966
+ */
13967
+ navigation: _enum(["app", "server"]).optional()
13723
13968
  });
13724
13969
  var AlertStatusSchema = _enum([
13725
13970
  "active",
@@ -42129,6 +42374,9 @@ var NcSystemEventKindSchema = _enum([
42129
42374
  "server-updated",
42130
42375
  "export-completed",
42131
42376
  "backup-completed",
42377
+ "alert-critical",
42378
+ "alert-error",
42379
+ "alert-critical-resolved",
42132
42380
  "camera-online",
42133
42381
  "camera-offline",
42134
42382
  "camera-disabled",
@@ -44164,202 +44412,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
44164
44412
  auth: "admin"
44165
44413
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
44166
44414
  /**
44167
- * Zod schemas for persisted record types.
44168
- *
44169
- * These schemas serve as the single source of truth for types that are
44170
- * stored in the settings-store backend and retrieved via tRPC. They
44171
- * replace the manual TypeScript interfaces with schema-derived types,
44172
- * enabling runtime validation when reading from the backend.
44173
- *
44174
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
44175
- * keeps the original name for backward compatibility.
44176
- */
44177
- /**
44178
- * Auth model (v2 — 2026-05-12 caps-only):
44179
- *
44180
- * Two principals:
44181
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
44182
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
44183
- *
44184
- * No role enum. There used to be `viewer / agent / scoped` and earlier
44185
- * `super_admin` — collapsed onto the single boolean because every
44186
- * non-admin caller is governed by the same scope-check rules; the
44187
- * distinction was only ever used to route role-specific procedures
44188
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
44189
- * with `isAdmin: false` + an explicit scope list.
44190
- */
44191
- /** Per-method access flavour. Materialised on every cap method via codegen. */
44192
- var MethodAccessSchema = _enum([
44193
- "view",
44194
- "create",
44195
- "delete"
44196
- ]);
44197
- /**
44198
- * A single scope grant. Three forms — checked in matcher with OR
44199
- * semantics; the first match decides whether the call passes:
44200
- *
44201
- * - `category` — broadest. `target: 'device' | 'system'` selects every
44202
- * cap with the matching `scope` declaration. New caps inherit grants
44203
- * automatically — adding a device cap to the codebase makes it
44204
- * reachable to every user with `category:device [...]` without a
44205
- * re-grant. Use this for "family viewer" / "operator" tiers.
44206
- *
44207
- * - `addon` — every cap that ships inside a given addon id. Niche;
44208
- * useful when an integration needs to interact with one specific
44209
- * addon's surface regardless of how many caps it exports.
44210
- *
44211
- * - `capability` — the most precise form. Single cap name. Use for
44212
- * integration tokens where you want to grant `addons.installPackage`
44213
- * and nothing else.
44214
- *
44215
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
44216
- * "give me everything" escape; there is no wildcard scope.
44217
- */
44218
- var AllowedProviderSchema = union([literal("*"), array(string())]);
44219
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
44220
- var CapScopeSchema = _enum(["device", "system"]);
44221
- /**
44222
- * DeviceSelector (scope model v3 — 2026-08-12).
44223
- *
44224
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
44225
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
44226
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
44227
- * AFTER the grant was minted — no re-grant, no re-login.
44228
- *
44229
- * - `all` — every device in the deployment. The broad viewer/operator
44230
- * lever without a `category` grant (a `category` grant also covers device
44231
- * caps that carry no deviceId; `all` is specifically the device set).
44232
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
44233
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
44234
- * is NOT covered until the grant is edited.
44235
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
44236
- * DYNAMIC. A device that changes type, or a new device of the type,
44237
- * re-resolves on the next request.
44238
- * - `locations` — every device whose operator-assigned `location` label is
44239
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
44240
- * null/unset location matches NO `locations` selector.
44241
- */
44242
- var DeviceSelectorSchema = discriminatedUnion("kind", [
44243
- object({ kind: literal("all") }),
44244
- object({
44245
- kind: literal("ids"),
44246
- ids: array(number().int()).min(1)
44247
- }),
44248
- object({
44249
- kind: literal("types"),
44250
- types: array(_enum(DeviceType)).min(1)
44251
- }),
44252
- object({
44253
- kind: literal("locations"),
44254
- locations: array(string().min(1)).min(1)
44255
- })
44256
- ]);
44257
- var DeviceTokenScopeSchema = object({
44258
- type: literal("device"),
44259
- /** The device SET this grant covers — resolved against the live fleet. */
44260
- selector: DeviceSelectorSchema,
44261
- access: array(MethodAccessSchema).min(1),
44262
- /**
44263
- * Whether a grant on a PARENT device transparently covers its accessory
44264
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
44265
- * Direction is parent → children ONLY.
44266
- *
44267
- * Absent → the matcher DERIVES it from the access flavour: `view`
44268
- * inherits (a camera viewer sees the camera's accessories), `create` /
44269
- * `delete` do NOT (actuating/removing a child is an explicit act the
44270
- * operator must grant on the child, not inherit from the parent). Set it
44271
- * explicitly to override that default per grant.
44272
- */
44273
- includeLinked: boolean().optional()
44274
- });
44275
- /**
44276
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
44277
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
44278
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
44279
- * EVERY parse path — stored records AND the JWT-carried scope arrays
44280
- * normalised at the request boundary ({@link normalizeTokenScopes} in
44281
- * `device-selector.ts`). Chosen over a one-time DB migration because a
44282
- * migration cannot reach a JWT already in a client's hands; parse-time
44283
- * migration covers both without a flag day. No cast — the raw object is read
44284
- * through `Reflect.get` (its static type is `unknown`).
44285
- */
44286
- function migrateLegacyTokenScope(raw) {
44287
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
44288
- if (Reflect.get(raw, "type") !== "device") return raw;
44289
- if (Reflect.get(raw, "selector") !== void 0) return raw;
44290
- const targets = Reflect.get(raw, "targets");
44291
- if (!Array.isArray(targets)) return raw;
44292
- return {
44293
- type: "device",
44294
- selector: {
44295
- kind: "ids",
44296
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
44297
- },
44298
- access: Reflect.get(raw, "access")
44299
- };
44300
- }
44301
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
44302
- object({
44303
- type: literal("category"),
44304
- target: CapScopeSchema,
44305
- access: array(MethodAccessSchema).min(1)
44306
- }),
44307
- object({
44308
- type: literal("capability"),
44309
- target: string(),
44310
- access: array(MethodAccessSchema).min(1)
44311
- }),
44312
- object({
44313
- type: literal("addon"),
44314
- target: string(),
44315
- access: array(MethodAccessSchema).min(1)
44316
- }),
44317
- DeviceTokenScopeSchema
44318
- ]));
44319
- object({
44320
- id: string(),
44321
- username: string(),
44322
- passwordHash: string(),
44323
- /**
44324
- * Admin bypass. When true, the middleware skips the scope-access
44325
- * check entirely. There is no other axis of privilege; the legacy
44326
- * role enum collapsed onto this boolean in v2.
44327
- */
44328
- isAdmin: boolean().default(false),
44329
- allowedProviders: AllowedProviderSchema,
44330
- allowedDevices: AllowedDevicesSchema,
44331
- /**
44332
- * Scopes granted to this user. Admins bypass; their `scopes` is
44333
- * ignored. Non-admins without scopes are locked out of every
44334
- * protected call.
44335
- */
44336
- scopes: array(TokenScopeSchema).default([]),
44337
- createdAt: number(),
44338
- updatedAt: number()
44339
- });
44340
- object({
44341
- id: string(),
44342
- label: string(),
44343
- isAdmin: boolean().default(false),
44344
- allowedProviders: AllowedProviderSchema,
44345
- allowedDevices: AllowedDevicesSchema,
44346
- tokenHash: string(),
44347
- tokenPrefix: string(),
44348
- createdAt: number(),
44349
- lastUsedAt: number().optional()
44350
- });
44351
- object({
44352
- id: string(),
44353
- userId: string(),
44354
- name: string(),
44355
- tokenHash: string(),
44356
- tokenPrefix: string(),
44357
- scopes: array(TokenScopeSchema),
44358
- expiresAt: number().nullish(),
44359
- lastUsedAt: number().nullish(),
44360
- createdAt: number()
44361
- });
44362
- /**
44363
44415
  * `oauth-integration` — a collection cap by which an addon declares
44364
44416
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
44365
44417
  * Each provider returns a static descriptor; the core enumerates them
@@ -51161,7 +51213,10 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
51161
51213
  }), method(object({ jobId: string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
51162
51214
  kind: "mutation",
51163
51215
  auth: "admin"
51164
- }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51216
+ }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({ locationIds: array(string()).readonly() }), object({
51217
+ clear: boolean(),
51218
+ repointLocationId: string().optional()
51219
+ }), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
51165
51220
  kind: "mutation",
51166
51221
  auth: "admin"
51167
51222
  }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
@@ -54596,6 +54651,11 @@ object({
54596
54651
  *
54597
54652
  * `kind: 'poll'` — cloud REST APIs typically have no push channel; the
54598
54653
  * provider refreshes the slice on an interval and eagerly after commands.
54654
+ *
54655
+ * UNKNOWN IS NOT OFF. Every field the appliance reports separately is
54656
+ * nullable: `null` means "not known right now" (the appliance has not said,
54657
+ * the link is down, or the description does not carry it) and is never
54658
+ * rendered or exported as `false` / `0`. `availability` says why.
54599
54659
  */
54600
54660
  var DishwasherStateSchema = _enum([
54601
54661
  "idle",
@@ -54605,112 +54665,227 @@ var DishwasherStateSchema = _enum([
54605
54665
  "error",
54606
54666
  "unavailable"
54607
54667
  ]);
54668
+ /**
54669
+ * The appliance's own operation state, uncollapsed. `state` above is the coarse
54670
+ * view for compact surfaces; this is what the appliance said.
54671
+ */
54672
+ var DishwasherOperationStateSchema = _enum([
54673
+ "Inactive",
54674
+ "Ready",
54675
+ "DelayedStart",
54676
+ "Run",
54677
+ "Pause",
54678
+ "ActionRequired",
54679
+ "Finished",
54680
+ "Error",
54681
+ "Aborting"
54682
+ ]);
54683
+ /**
54684
+ * Why fields may be `null`:
54685
+ * - `available` — the link is up and the description is loaded;
54686
+ * - `offline` — the local link is down (values are unknown, not last-known);
54687
+ * - `description-missing` — the link is up but the appliance's description could not
54688
+ * be loaded, so its values cannot be decoded.
54689
+ */
54690
+ var DishwasherAvailabilitySchema = _enum([
54691
+ "available",
54692
+ "offline",
54693
+ "description-missing"
54694
+ ]);
54608
54695
  var DishwasherConsumableLevelSchema = _enum([
54609
54696
  "ok",
54610
54697
  "low",
54611
54698
  "empty"
54612
54699
  ]);
54613
54700
  object({
54701
+ availability: DishwasherAvailabilitySchema,
54702
+ /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
54614
54703
  state: DishwasherStateSchema,
54615
- /** Active program id/name, or null when none selected / unknown. */
54704
+ /** The appliance's operation state as reported; null when not known. */
54705
+ operationState: DishwasherOperationStateSchema.nullable(),
54706
+ /** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
54616
54707
  program: string().nullable(),
54617
- /** Program tokens the hardware accepts — drives the UI selector. */
54708
+ /** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
54709
+ selectedProgram: string().nullable(),
54710
+ /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
54618
54711
  availablePrograms: array(string()),
54619
- /** Minutes remaining on the active cycle, or null when not running. */
54620
- remainingMinutes: number().int().nonnegative().nullable(),
54712
+ /** Seconds remaining on the active cycle, or null when not running / not known. */
54713
+ remainingSeconds: number().int().nonnegative().nullable(),
54714
+ /** Seconds the delayed start is set to (time until the cycle starts), or null. */
54715
+ delayedStartSeconds: number().int().nonnegative().nullable(),
54621
54716
  /** Cycle completion 0..100, or null when not applicable. */
54622
54717
  progressPercent: number().min(0).max(100).nullable(),
54623
- /** True when the door is reported open. */
54624
- doorOpen: boolean(),
54625
- /** True when remote start is allowed (door closed, power on, etc.). */
54626
- remoteStartAllowed: boolean(),
54627
- /** Main power / switched-on state. */
54628
- powerOn: boolean(),
54718
+ /** True when the door is reported open; null when the door state is not known. */
54719
+ doorOpen: boolean().nullable(),
54720
+ /** True when the door is latched (locked) during a cycle; null when not reported. */
54721
+ doorLocked: boolean().nullable(),
54722
+ /** True when remote start is allowed (door closed, power on, etc.); null when not known. */
54723
+ remoteStartAllowed: boolean().nullable(),
54724
+ /** True when the appliance accepts remote control now; null when not known. */
54725
+ remoteControlActive: boolean().nullable(),
54726
+ /** True while somebody operates the appliance at its panel; null when not reported. */
54727
+ localControlActive: boolean().nullable(),
54728
+ /** Main power / switched-on state; null when not known. */
54729
+ powerOn: boolean().nullable(),
54730
+ /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
54731
+ powerState: string().nullable(),
54629
54732
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
54630
54733
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
54631
- halfLoad: boolean(),
54632
- hygienePlus: boolean(),
54734
+ /** Option states: null when the appliance does not expose the option or has not said. */
54735
+ halfLoad: boolean().nullable(),
54736
+ hygienePlus: boolean().nullable(),
54633
54737
  /** Extra dry option when the appliance exposes it. */
54634
- extraDry: boolean(),
54738
+ extraDry: boolean().nullable(),
54635
54739
  /** Intensive zone (lower basket) when the appliance exposes it. */
54636
- intensiveZone: boolean(),
54740
+ intensiveZone: boolean().nullable(),
54637
54741
  /** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
54638
- varioSpeedPlus: boolean(),
54639
- /** Child lock (controls disabled on the appliance). */
54640
- childLock: boolean(),
54742
+ varioSpeedPlus: boolean().nullable(),
54743
+ /** Child lock (controls disabled on the appliance); null when not known. */
54744
+ childLock: boolean().nullable(),
54745
+ /** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
54746
+ activeEvents: array(string()),
54747
+ /** Numeric error code when the appliance reports one; null otherwise. */
54641
54748
  errorCode: number().nullable(),
54749
+ /** Name of the raised alert-level event while the appliance is in error; null otherwise. */
54642
54750
  errorLabel: string().nullable(),
54751
+ /** Ms epoch of the last value received from the appliance; 0 = never. */
54643
54752
  lastFetchedAt: number()
54644
54753
  });
54645
- DeviceType.Dishwasher, method(object({ deviceId: number().int().nonnegative() }), _void(), {
54754
+ var DeviceIdSchema = number().int().nonnegative();
54755
+ /** A value a program option or setting can take. */
54756
+ var DishwasherValueSchema = union([
54757
+ boolean(),
54758
+ string(),
54759
+ number()
54760
+ ]);
54761
+ var DishwasherAccessSchema = _enum([
54762
+ "none",
54763
+ "read",
54764
+ "readWrite",
54765
+ "writeOnly",
54766
+ "readStatic"
54767
+ ]);
54768
+ /**
54769
+ * One option or setting the appliance declares, with the constraints its description
54770
+ * gives. A `readWrite` descriptor that is `available` is what `setOption` accepts.
54771
+ */
54772
+ var DishwasherOptionDescriptorSchema = object({
54773
+ /** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
54774
+ key: string(),
54775
+ /** Last segment of the key, for display. */
54776
+ name: string(),
54777
+ type: _enum([
54778
+ "boolean",
54779
+ "number",
54780
+ "enum",
54781
+ "string"
54782
+ ]),
54783
+ access: DishwasherAccessSchema,
54784
+ /** The appliance reports this entity as currently available. */
54785
+ available: boolean(),
54786
+ /** Unit the description declares for a number; null when it declares none. */
54787
+ unit: string().nullable(),
54788
+ min: number().nullable(),
54789
+ max: number().nullable(),
54790
+ step: number().nullable(),
54791
+ /** Allowed members of an enum; null for other types. */
54792
+ enumValues: array(string()).nullable(),
54793
+ defaultValue: DishwasherValueSchema.nullable()
54794
+ });
54795
+ var DishwasherProgramSchema = object({
54796
+ /** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
54797
+ key: string(),
54798
+ name: string(),
54799
+ /** The appliance currently offers this program. */
54800
+ available: boolean(),
54801
+ /** The options this program lists, with the program-level access / availability / default. */
54802
+ options: array(DishwasherOptionDescriptorSchema)
54803
+ });
54804
+ var DishwasherOptionsSchema = object({
54805
+ availability: DishwasherAvailabilitySchema,
54806
+ /** What the appliance can be told to do, from the commands its description declares. */
54807
+ supportsStart: boolean(),
54808
+ supportsPause: boolean(),
54809
+ supportsResume: boolean(),
54810
+ supportsStop: boolean(),
54811
+ supportsPower: boolean(),
54812
+ /** Every program the description lists, with its options. */
54813
+ programs: array(DishwasherProgramSchema),
54814
+ /** Every option and setting entity the description lists (programs reference these by key). */
54815
+ options: array(DishwasherOptionDescriptorSchema)
54816
+ });
54817
+ DeviceType.Dishwasher, method(object({
54818
+ deviceId: DeviceIdSchema,
54819
+ program: string().min(1).optional(),
54820
+ options: record(string(), DishwasherValueSchema).optional()
54821
+ }), _void(), {
54646
54822
  kind: "mutation",
54647
54823
  auth: "protected"
54648
- }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
54824
+ }), method(object({ deviceId: DeviceIdSchema }), _void(), {
54649
54825
  kind: "mutation",
54650
54826
  auth: "protected"
54651
- }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
54827
+ }), method(object({ deviceId: DeviceIdSchema }), _void(), {
54828
+ kind: "mutation",
54829
+ auth: "protected"
54830
+ }), method(object({ deviceId: DeviceIdSchema }), _void(), {
54652
54831
  kind: "mutation",
54653
54832
  auth: "protected"
54654
54833
  }), method(object({
54655
- deviceId: number().int().nonnegative(),
54834
+ deviceId: DeviceIdSchema,
54656
54835
  program: string().min(1)
54657
54836
  }), _void(), {
54658
54837
  kind: "mutation",
54659
54838
  auth: "protected"
54660
54839
  }), method(object({
54661
- deviceId: number().int().nonnegative(),
54840
+ deviceId: DeviceIdSchema,
54662
54841
  on: boolean()
54663
54842
  }), _void(), {
54664
54843
  kind: "mutation",
54665
54844
  auth: "protected"
54666
54845
  }), method(object({
54667
- deviceId: number().int().nonnegative(),
54846
+ deviceId: DeviceIdSchema,
54668
54847
  on: boolean()
54669
54848
  }), _void(), {
54670
54849
  kind: "mutation",
54671
54850
  auth: "protected"
54672
54851
  }), method(object({
54673
- deviceId: number().int().nonnegative(),
54852
+ deviceId: DeviceIdSchema,
54674
54853
  on: boolean()
54675
54854
  }), _void(), {
54676
54855
  kind: "mutation",
54677
54856
  auth: "protected"
54678
54857
  }), method(object({
54679
- deviceId: number().int().nonnegative(),
54858
+ deviceId: DeviceIdSchema,
54680
54859
  on: boolean()
54681
54860
  }), _void(), {
54682
54861
  kind: "mutation",
54683
54862
  auth: "protected"
54684
54863
  }), method(object({
54685
- deviceId: number().int().nonnegative(),
54864
+ deviceId: DeviceIdSchema,
54686
54865
  on: boolean()
54687
54866
  }), _void(), {
54688
54867
  kind: "mutation",
54689
54868
  auth: "protected"
54690
54869
  }), method(object({
54691
- deviceId: number().int().nonnegative(),
54870
+ deviceId: DeviceIdSchema,
54692
54871
  on: boolean()
54693
54872
  }), _void(), {
54694
54873
  kind: "mutation",
54695
54874
  auth: "protected"
54696
54875
  }), method(object({
54697
- deviceId: number().int().nonnegative(),
54876
+ deviceId: DeviceIdSchema,
54698
54877
  on: boolean()
54699
54878
  }), _void(), {
54700
54879
  kind: "mutation",
54701
54880
  auth: "protected"
54702
54881
  }), method(object({
54703
- deviceId: number().int().nonnegative(),
54882
+ deviceId: DeviceIdSchema,
54704
54883
  key: string().min(1),
54705
- value: union([
54706
- boolean(),
54707
- string(),
54708
- number()
54709
- ])
54884
+ value: DishwasherValueSchema
54710
54885
  }), _void(), {
54711
54886
  kind: "mutation",
54712
54887
  auth: "protected"
54713
- });
54888
+ }), method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" });
54714
54889
  object({
54715
54890
  /** Ms epoch of the last press. null = never observed since this provider started. */
54716
54891
  lastPressedAt: number().nullable(),
@@ -64868,6 +65043,12 @@ Object.freeze({
64868
65043
  addonId: null,
64869
65044
  access: "view"
64870
65045
  },
65046
+ "dishwasher.getOptions": {
65047
+ capName: "dishwasher",
65048
+ capScope: "device",
65049
+ addonId: null,
65050
+ access: "view"
65051
+ },
64871
65052
  "dishwasher.getStatus": {
64872
65053
  capName: "dishwasher",
64873
65054
  capScope: "device",
@@ -64880,6 +65061,12 @@ Object.freeze({
64880
65061
  addonId: null,
64881
65062
  access: "create"
64882
65063
  },
65064
+ "dishwasher.resume": {
65065
+ capName: "dishwasher",
65066
+ capScope: "device",
65067
+ addonId: null,
65068
+ access: "create"
65069
+ },
64883
65070
  "dishwasher.setChildLock": {
64884
65071
  capName: "dishwasher",
64885
65072
  capScope: "device",
@@ -69380,6 +69567,12 @@ Object.freeze({
69380
69567
  addonId: null,
69381
69568
  access: "view"
69382
69569
  },
69570
+ "storageMigration.moverClearance": {
69571
+ capName: "storage-migration",
69572
+ capScope: "system",
69573
+ addonId: null,
69574
+ access: "view"
69575
+ },
69383
69576
  "storageMigration.movers": {
69384
69577
  capName: "storage-migration",
69385
69578
  capScope: "system",
@@ -71573,6 +71766,11 @@ Object.freeze({
71573
71766
  form: "single",
71574
71767
  optional: false
71575
71768
  }],
71769
+ "dishwasher.getOptions": [{
71770
+ name: "deviceId",
71771
+ form: "single",
71772
+ optional: false
71773
+ }],
71576
71774
  "dishwasher.getStatus": [{
71577
71775
  name: "deviceId",
71578
71776
  form: "single",
@@ -71583,6 +71781,11 @@ Object.freeze({
71583
71781
  form: "single",
71584
71782
  optional: false
71585
71783
  }],
71784
+ "dishwasher.resume": [{
71785
+ name: "deviceId",
71786
+ form: "single",
71787
+ optional: false
71788
+ }],
71586
71789
  "dishwasher.setChildLock": [{
71587
71790
  name: "deviceId",
71588
71791
  form: "single",
@@ -73669,6 +73872,9 @@ new Map(Object.entries({
73669
73872
  "wrapper-update-available": "system",
73670
73873
  "backup-completed": "system",
73671
73874
  "export-completed": "system",
73875
+ "alert-critical": "system",
73876
+ "alert-error": "system",
73877
+ "alert-critical-resolved": "system",
73672
73878
  "storage-location-low": "system",
73673
73879
  "storage-location-critical": "system",
73674
73880
  "storage-location-ok": "system",
@@ -73793,6 +73999,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
73793
73999
  "storage-location-ok"
73794
74000
  ]
73795
74001
  },
74002
+ {
74003
+ id: "alerts",
74004
+ family: "system",
74005
+ label: "Alerts",
74006
+ kinds: [
74007
+ "alert-critical",
74008
+ "alert-error",
74009
+ "alert-critical-resolved"
74010
+ ]
74011
+ },
73796
74012
  {
73797
74013
  id: "alarm",
73798
74014
  family: "alarm",
@@ -73837,6 +74053,21 @@ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.ent
73837
74053
  return [[descriptor.kind, field]];
73838
74054
  })));
73839
74055
  Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
74056
+ object({
74057
+ phase: _enum(["raised", "resolved"]),
74058
+ episodeId: string().min(1),
74059
+ alertId: string().min(1),
74060
+ severity: AlertSeveritySchema,
74061
+ category: string(),
74062
+ title: string(),
74063
+ message: string(),
74064
+ sourceType: string().optional(),
74065
+ sourceId: string().optional(),
74066
+ nodeId: string().optional(),
74067
+ /** The alert's own action link (where the operator acts on it), when it has one. */
74068
+ actionUrl: string().optional(),
74069
+ at: number()
74070
+ });
73840
74071
  var RULE_BODY_ONLY = ["body"];
73841
74072
  var RULE_TEXT = ["title", "body"];
73842
74073
  var BATTERY = ["device-battery-low", "device-battery-normal"];
@@ -73846,6 +74077,11 @@ var TANK = [
73846
74077
  "device-tank-full",
73847
74078
  "device-tank-normal"
73848
74079
  ];
74080
+ var ALERT_EPISODE = [
74081
+ "alert-critical",
74082
+ "alert-error",
74083
+ "alert-critical-resolved"
74084
+ ];
73849
74085
  var UPDATES = [
73850
74086
  "addon-update-available",
73851
74087
  "server-update-available",
@@ -74038,14 +74274,14 @@ var STATE_SUMMARY_VARS = [
74038
74274
  ([...RULE_TEXT], [...CONSUMABLE]),
74039
74275
  ([...RULE_TEXT], [...TANK]),
74040
74276
  [...RULE_TEXT],
74041
- ([...RULE_TEXT], [...UPDATES]),
74042
- ([...RULE_TEXT], [...UPDATES]),
74043
- [...RULE_TEXT],
74277
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
74278
+ ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
74044
74279
  [...RULE_TEXT],
74045
74280
  [...RULE_TEXT],
74046
74281
  [...RULE_TEXT],
74047
74282
  [...RULE_TEXT],
74048
74283
  [...RULE_TEXT],
74284
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74049
74285
  [...RULE_TEXT],
74050
74286
  [...RULE_TEXT],
74051
74287
  [...RULE_TEXT],
@@ -74063,7 +74299,11 @@ var STATE_SUMMARY_VARS = [
74063
74299
  [...RULE_TEXT],
74064
74300
  [...RULE_TEXT],
74065
74301
  [...RULE_TEXT],
74066
- [...RULE_TEXT],
74302
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74303
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74304
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74305
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74306
+ ([...RULE_TEXT], [...ALERT_EPISODE]),
74067
74307
  [...RULE_TEXT],
74068
74308
  [...RULE_TEXT],
74069
74309
  [...RULE_TEXT],