@camstack/addon-provider-dreame 0.2.136 → 0.2.137

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 +229 -196
  2. package/dist/addon.mjs +229 -196
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7841,6 +7841,12 @@ function normalizeAddonInitResult(result) {
7841
7841
  if (Array.isArray(result)) return { providers: result };
7842
7842
  return result;
7843
7843
  }
7844
+ /**
7845
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7846
+ * and validates them (`share-token.service.ts` builds its enum from this
7847
+ * list); a data plane names the kinds it ACCEPTS in `share`.
7848
+ */
7849
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7844
7850
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
7845
7851
  var PeerBytesTicketSchema = object({
7846
7852
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -12520,6 +12526,229 @@ var ConvertResultSchema = object({
12520
12526
  files: array(string()).readonly()
12521
12527
  })).readonly()
12522
12528
  });
12529
+ /**
12530
+ * Zod schemas for persisted record types.
12531
+ *
12532
+ * These schemas serve as the single source of truth for types that are
12533
+ * stored in the settings-store backend and retrieved via tRPC. They
12534
+ * replace the manual TypeScript interfaces with schema-derived types,
12535
+ * enabling runtime validation when reading from the backend.
12536
+ *
12537
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
12538
+ * keeps the original name for backward compatibility.
12539
+ */
12540
+ /**
12541
+ * Auth model (v2 — 2026-05-12 caps-only):
12542
+ *
12543
+ * Two principals:
12544
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
12545
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
12546
+ *
12547
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
12548
+ * `super_admin` — collapsed onto the single boolean because every
12549
+ * non-admin caller is governed by the same scope-check rules; the
12550
+ * distinction was only ever used to route role-specific procedures
12551
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12552
+ * with `isAdmin: false` + an explicit scope list.
12553
+ */
12554
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
12555
+ var MethodAccessSchema = _enum([
12556
+ "view",
12557
+ "create",
12558
+ "delete"
12559
+ ]);
12560
+ /**
12561
+ * A single scope grant. Three forms — checked in matcher with OR
12562
+ * semantics; the first match decides whether the call passes:
12563
+ *
12564
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
12565
+ * cap with the matching `scope` declaration. New caps inherit grants
12566
+ * automatically — adding a device cap to the codebase makes it
12567
+ * reachable to every user with `category:device [...]` without a
12568
+ * re-grant. Use this for "family viewer" / "operator" tiers.
12569
+ *
12570
+ * - `addon` — every cap that ships inside a given addon id. Niche;
12571
+ * useful when an integration needs to interact with one specific
12572
+ * addon's surface regardless of how many caps it exports.
12573
+ *
12574
+ * - `capability` — the most precise form. Single cap name. Use for
12575
+ * integration tokens where you want to grant `addons.installPackage`
12576
+ * and nothing else.
12577
+ *
12578
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
12579
+ * "give me everything" escape; there is no wildcard scope.
12580
+ */
12581
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
12582
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
12583
+ var CapScopeSchema = _enum(["device", "system"]);
12584
+ /**
12585
+ * DeviceSelector (scope model v3 — 2026-08-12).
12586
+ *
12587
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
12588
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
12589
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
12590
+ * AFTER the grant was minted — no re-grant, no re-login.
12591
+ *
12592
+ * - `all` — every device in the deployment. The broad viewer/operator
12593
+ * lever without a `category` grant (a `category` grant also covers device
12594
+ * caps that carry no deviceId; `all` is specifically the device set).
12595
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
12596
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
12597
+ * is NOT covered until the grant is edited.
12598
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
12599
+ * DYNAMIC. A device that changes type, or a new device of the type,
12600
+ * re-resolves on the next request.
12601
+ * - `locations` — every device whose operator-assigned `location` label is
12602
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
12603
+ * null/unset location matches NO `locations` selector.
12604
+ */
12605
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
12606
+ object({ kind: literal("all") }),
12607
+ object({
12608
+ kind: literal("ids"),
12609
+ ids: array(number().int()).min(1)
12610
+ }),
12611
+ object({
12612
+ kind: literal("types"),
12613
+ types: array(_enum(DeviceType)).min(1)
12614
+ }),
12615
+ object({
12616
+ kind: literal("locations"),
12617
+ locations: array(string().min(1)).min(1)
12618
+ })
12619
+ ]);
12620
+ var DeviceTokenScopeSchema = object({
12621
+ type: literal("device"),
12622
+ /** The device SET this grant covers — resolved against the live fleet. */
12623
+ selector: DeviceSelectorSchema,
12624
+ access: array(MethodAccessSchema).min(1),
12625
+ /**
12626
+ * Whether a grant on a PARENT device transparently covers its accessory
12627
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
12628
+ * Direction is parent → children ONLY.
12629
+ *
12630
+ * Absent → the matcher DERIVES it from the access flavour: `view`
12631
+ * inherits (a camera viewer sees the camera's accessories), `create` /
12632
+ * `delete` do NOT (actuating/removing a child is an explicit act the
12633
+ * operator must grant on the child, not inherit from the parent). Set it
12634
+ * explicitly to override that default per grant.
12635
+ */
12636
+ includeLinked: boolean().optional()
12637
+ });
12638
+ /**
12639
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
12640
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
12641
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
12642
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
12643
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
12644
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
12645
+ * migration cannot reach a JWT already in a client's hands; parse-time
12646
+ * migration covers both without a flag day. No cast — the raw object is read
12647
+ * through `Reflect.get` (its static type is `unknown`).
12648
+ */
12649
+ function migrateLegacyTokenScope(raw) {
12650
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
12651
+ if (Reflect.get(raw, "type") !== "device") return raw;
12652
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
12653
+ const targets = Reflect.get(raw, "targets");
12654
+ if (!Array.isArray(targets)) return raw;
12655
+ return {
12656
+ type: "device",
12657
+ selector: {
12658
+ kind: "ids",
12659
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
12660
+ },
12661
+ access: Reflect.get(raw, "access")
12662
+ };
12663
+ }
12664
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
12665
+ object({
12666
+ type: literal("category"),
12667
+ target: CapScopeSchema,
12668
+ access: array(MethodAccessSchema).min(1)
12669
+ }),
12670
+ object({
12671
+ type: literal("capability"),
12672
+ target: string(),
12673
+ access: array(MethodAccessSchema).min(1)
12674
+ }),
12675
+ object({
12676
+ type: literal("addon"),
12677
+ target: string(),
12678
+ access: array(MethodAccessSchema).min(1)
12679
+ }),
12680
+ DeviceTokenScopeSchema
12681
+ ]));
12682
+ object({
12683
+ id: string(),
12684
+ username: string(),
12685
+ passwordHash: string(),
12686
+ /**
12687
+ * Admin bypass. When true, the middleware skips the scope-access
12688
+ * check entirely. There is no other axis of privilege; the legacy
12689
+ * role enum collapsed onto this boolean in v2.
12690
+ */
12691
+ isAdmin: boolean().default(false),
12692
+ allowedProviders: AllowedProviderSchema,
12693
+ allowedDevices: AllowedDevicesSchema,
12694
+ /**
12695
+ * Scopes granted to this user. Admins bypass; their `scopes` is
12696
+ * ignored. Non-admins without scopes are locked out of every
12697
+ * protected call.
12698
+ */
12699
+ scopes: array(TokenScopeSchema).default([]),
12700
+ createdAt: number(),
12701
+ updatedAt: number()
12702
+ });
12703
+ object({
12704
+ id: string(),
12705
+ label: string(),
12706
+ isAdmin: boolean().default(false),
12707
+ allowedProviders: AllowedProviderSchema,
12708
+ allowedDevices: AllowedDevicesSchema,
12709
+ tokenHash: string(),
12710
+ tokenPrefix: string(),
12711
+ createdAt: number(),
12712
+ lastUsedAt: number().optional()
12713
+ });
12714
+ object({
12715
+ id: string(),
12716
+ userId: string(),
12717
+ name: string(),
12718
+ tokenHash: string(),
12719
+ tokenPrefix: string(),
12720
+ scopes: array(TokenScopeSchema),
12721
+ expiresAt: number().nullish(),
12722
+ lastUsedAt: number().nullish(),
12723
+ createdAt: number()
12724
+ });
12725
+ /** What a share-view grant lets its holder see. */
12726
+ var ShareViewGrantSchema = object({
12727
+ kind: _enum(SHARE_VIEW_KINDS),
12728
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
12729
+ /** Talk-back, opt-in at mint time; absent means off. */
12730
+ talk: boolean().optional()
12731
+ });
12732
+ var ShareViewScopeSchema = object({
12733
+ type: literal("share-view"),
12734
+ grant: ShareViewGrantSchema
12735
+ });
12736
+ var AddonRoutesScopeSchema = object({
12737
+ type: literal("addon-routes"),
12738
+ access: array(MethodAccessSchema).min(1)
12739
+ });
12740
+ var CredentialScopeSchema = union([
12741
+ literal("*"),
12742
+ ShareViewScopeSchema,
12743
+ AddonRoutesScopeSchema,
12744
+ TokenScopeSchema
12745
+ ]);
12746
+ object({
12747
+ kind: literal("credential"),
12748
+ sub: string().min(1),
12749
+ jti: string().min(16),
12750
+ scopes: array(CredentialScopeSchema).min(1)
12751
+ });
12523
12752
  _enum(["new-session", "step-up"]);
12524
12753
  /** The languages the hub's app landing pages are written in (D858). */
12525
12754
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -44026,202 +44255,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
44026
44255
  auth: "admin"
44027
44256
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
44028
44257
  /**
44029
- * Zod schemas for persisted record types.
44030
- *
44031
- * These schemas serve as the single source of truth for types that are
44032
- * stored in the settings-store backend and retrieved via tRPC. They
44033
- * replace the manual TypeScript interfaces with schema-derived types,
44034
- * enabling runtime validation when reading from the backend.
44035
- *
44036
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
44037
- * keeps the original name for backward compatibility.
44038
- */
44039
- /**
44040
- * Auth model (v2 — 2026-05-12 caps-only):
44041
- *
44042
- * Two principals:
44043
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
44044
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
44045
- *
44046
- * No role enum. There used to be `viewer / agent / scoped` and earlier
44047
- * `super_admin` — collapsed onto the single boolean because every
44048
- * non-admin caller is governed by the same scope-check rules; the
44049
- * distinction was only ever used to route role-specific procedures
44050
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
44051
- * with `isAdmin: false` + an explicit scope list.
44052
- */
44053
- /** Per-method access flavour. Materialised on every cap method via codegen. */
44054
- var MethodAccessSchema = _enum([
44055
- "view",
44056
- "create",
44057
- "delete"
44058
- ]);
44059
- /**
44060
- * A single scope grant. Three forms — checked in matcher with OR
44061
- * semantics; the first match decides whether the call passes:
44062
- *
44063
- * - `category` — broadest. `target: 'device' | 'system'` selects every
44064
- * cap with the matching `scope` declaration. New caps inherit grants
44065
- * automatically — adding a device cap to the codebase makes it
44066
- * reachable to every user with `category:device [...]` without a
44067
- * re-grant. Use this for "family viewer" / "operator" tiers.
44068
- *
44069
- * - `addon` — every cap that ships inside a given addon id. Niche;
44070
- * useful when an integration needs to interact with one specific
44071
- * addon's surface regardless of how many caps it exports.
44072
- *
44073
- * - `capability` — the most precise form. Single cap name. Use for
44074
- * integration tokens where you want to grant `addons.installPackage`
44075
- * and nothing else.
44076
- *
44077
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
44078
- * "give me everything" escape; there is no wildcard scope.
44079
- */
44080
- var AllowedProviderSchema = union([literal("*"), array(string())]);
44081
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
44082
- var CapScopeSchema = _enum(["device", "system"]);
44083
- /**
44084
- * DeviceSelector (scope model v3 — 2026-08-12).
44085
- *
44086
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
44087
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
44088
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
44089
- * AFTER the grant was minted — no re-grant, no re-login.
44090
- *
44091
- * - `all` — every device in the deployment. The broad viewer/operator
44092
- * lever without a `category` grant (a `category` grant also covers device
44093
- * caps that carry no deviceId; `all` is specifically the device set).
44094
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
44095
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
44096
- * is NOT covered until the grant is edited.
44097
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
44098
- * DYNAMIC. A device that changes type, or a new device of the type,
44099
- * re-resolves on the next request.
44100
- * - `locations` — every device whose operator-assigned `location` label is
44101
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
44102
- * null/unset location matches NO `locations` selector.
44103
- */
44104
- var DeviceSelectorSchema = discriminatedUnion("kind", [
44105
- object({ kind: literal("all") }),
44106
- object({
44107
- kind: literal("ids"),
44108
- ids: array(number().int()).min(1)
44109
- }),
44110
- object({
44111
- kind: literal("types"),
44112
- types: array(_enum(DeviceType)).min(1)
44113
- }),
44114
- object({
44115
- kind: literal("locations"),
44116
- locations: array(string().min(1)).min(1)
44117
- })
44118
- ]);
44119
- var DeviceTokenScopeSchema = object({
44120
- type: literal("device"),
44121
- /** The device SET this grant covers — resolved against the live fleet. */
44122
- selector: DeviceSelectorSchema,
44123
- access: array(MethodAccessSchema).min(1),
44124
- /**
44125
- * Whether a grant on a PARENT device transparently covers its accessory
44126
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
44127
- * Direction is parent → children ONLY.
44128
- *
44129
- * Absent → the matcher DERIVES it from the access flavour: `view`
44130
- * inherits (a camera viewer sees the camera's accessories), `create` /
44131
- * `delete` do NOT (actuating/removing a child is an explicit act the
44132
- * operator must grant on the child, not inherit from the parent). Set it
44133
- * explicitly to override that default per grant.
44134
- */
44135
- includeLinked: boolean().optional()
44136
- });
44137
- /**
44138
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
44139
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
44140
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
44141
- * EVERY parse path — stored records AND the JWT-carried scope arrays
44142
- * normalised at the request boundary ({@link normalizeTokenScopes} in
44143
- * `device-selector.ts`). Chosen over a one-time DB migration because a
44144
- * migration cannot reach a JWT already in a client's hands; parse-time
44145
- * migration covers both without a flag day. No cast — the raw object is read
44146
- * through `Reflect.get` (its static type is `unknown`).
44147
- */
44148
- function migrateLegacyTokenScope(raw) {
44149
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
44150
- if (Reflect.get(raw, "type") !== "device") return raw;
44151
- if (Reflect.get(raw, "selector") !== void 0) return raw;
44152
- const targets = Reflect.get(raw, "targets");
44153
- if (!Array.isArray(targets)) return raw;
44154
- return {
44155
- type: "device",
44156
- selector: {
44157
- kind: "ids",
44158
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
44159
- },
44160
- access: Reflect.get(raw, "access")
44161
- };
44162
- }
44163
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
44164
- object({
44165
- type: literal("category"),
44166
- target: CapScopeSchema,
44167
- access: array(MethodAccessSchema).min(1)
44168
- }),
44169
- object({
44170
- type: literal("capability"),
44171
- target: string(),
44172
- access: array(MethodAccessSchema).min(1)
44173
- }),
44174
- object({
44175
- type: literal("addon"),
44176
- target: string(),
44177
- access: array(MethodAccessSchema).min(1)
44178
- }),
44179
- DeviceTokenScopeSchema
44180
- ]));
44181
- object({
44182
- id: string(),
44183
- username: string(),
44184
- passwordHash: string(),
44185
- /**
44186
- * Admin bypass. When true, the middleware skips the scope-access
44187
- * check entirely. There is no other axis of privilege; the legacy
44188
- * role enum collapsed onto this boolean in v2.
44189
- */
44190
- isAdmin: boolean().default(false),
44191
- allowedProviders: AllowedProviderSchema,
44192
- allowedDevices: AllowedDevicesSchema,
44193
- /**
44194
- * Scopes granted to this user. Admins bypass; their `scopes` is
44195
- * ignored. Non-admins without scopes are locked out of every
44196
- * protected call.
44197
- */
44198
- scopes: array(TokenScopeSchema).default([]),
44199
- createdAt: number(),
44200
- updatedAt: number()
44201
- });
44202
- object({
44203
- id: string(),
44204
- label: string(),
44205
- isAdmin: boolean().default(false),
44206
- allowedProviders: AllowedProviderSchema,
44207
- allowedDevices: AllowedDevicesSchema,
44208
- tokenHash: string(),
44209
- tokenPrefix: string(),
44210
- createdAt: number(),
44211
- lastUsedAt: number().optional()
44212
- });
44213
- object({
44214
- id: string(),
44215
- userId: string(),
44216
- name: string(),
44217
- tokenHash: string(),
44218
- tokenPrefix: string(),
44219
- scopes: array(TokenScopeSchema),
44220
- expiresAt: number().nullish(),
44221
- lastUsedAt: number().nullish(),
44222
- createdAt: number()
44223
- });
44224
- /**
44225
44258
  * `oauth-integration` — a collection cap by which an addon declares
44226
44259
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
44227
44260
  * Each provider returns a static descriptor; the core enumerates them
package/dist/addon.mjs CHANGED
@@ -7838,6 +7838,12 @@ function normalizeAddonInitResult(result) {
7838
7838
  if (Array.isArray(result)) return { providers: result };
7839
7839
  return result;
7840
7840
  }
7841
+ /**
7842
+ * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7843
+ * and validates them (`share-token.service.ts` builds its enum from this
7844
+ * list); a data plane names the kinds it ACCEPTS in `share`.
7845
+ */
7846
+ var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7841
7847
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
7842
7848
  var PeerBytesTicketSchema = object({
7843
7849
  /** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
@@ -12517,6 +12523,229 @@ var ConvertResultSchema = object({
12517
12523
  files: array(string()).readonly()
12518
12524
  })).readonly()
12519
12525
  });
12526
+ /**
12527
+ * Zod schemas for persisted record types.
12528
+ *
12529
+ * These schemas serve as the single source of truth for types that are
12530
+ * stored in the settings-store backend and retrieved via tRPC. They
12531
+ * replace the manual TypeScript interfaces with schema-derived types,
12532
+ * enabling runtime validation when reading from the backend.
12533
+ *
12534
+ * Convention: each schema is named `<Type>Schema`, the inferred TS type
12535
+ * keeps the original name for backward compatibility.
12536
+ */
12537
+ /**
12538
+ * Auth model (v2 — 2026-05-12 caps-only):
12539
+ *
12540
+ * Two principals:
12541
+ * - `isAdmin: true` — full bypass. Admin scope set is ignored.
12542
+ * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
12543
+ *
12544
+ * No role enum. There used to be `viewer / agent / scoped` and earlier
12545
+ * `super_admin` — collapsed onto the single boolean because every
12546
+ * non-admin caller is governed by the same scope-check rules; the
12547
+ * distinction was only ever used to route role-specific procedures
12548
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12549
+ * with `isAdmin: false` + an explicit scope list.
12550
+ */
12551
+ /** Per-method access flavour. Materialised on every cap method via codegen. */
12552
+ var MethodAccessSchema = _enum([
12553
+ "view",
12554
+ "create",
12555
+ "delete"
12556
+ ]);
12557
+ /**
12558
+ * A single scope grant. Three forms — checked in matcher with OR
12559
+ * semantics; the first match decides whether the call passes:
12560
+ *
12561
+ * - `category` — broadest. `target: 'device' | 'system'` selects every
12562
+ * cap with the matching `scope` declaration. New caps inherit grants
12563
+ * automatically — adding a device cap to the codebase makes it
12564
+ * reachable to every user with `category:device [...]` without a
12565
+ * re-grant. Use this for "family viewer" / "operator" tiers.
12566
+ *
12567
+ * - `addon` — every cap that ships inside a given addon id. Niche;
12568
+ * useful when an integration needs to interact with one specific
12569
+ * addon's surface regardless of how many caps it exports.
12570
+ *
12571
+ * - `capability` — the most precise form. Single cap name. Use for
12572
+ * integration tokens where you want to grant `addons.installPackage`
12573
+ * and nothing else.
12574
+ *
12575
+ * `access` is REQUIRED with min 1 element. `admin` bypass is the
12576
+ * "give me everything" escape; there is no wildcard scope.
12577
+ */
12578
+ var AllowedProviderSchema = union([literal("*"), array(string())]);
12579
+ var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
12580
+ var CapScopeSchema = _enum(["device", "system"]);
12581
+ /**
12582
+ * DeviceSelector (scope model v3 — 2026-08-12).
12583
+ *
12584
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
12585
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
12586
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
12587
+ * AFTER the grant was minted — no re-grant, no re-login.
12588
+ *
12589
+ * - `all` — every device in the deployment. The broad viewer/operator
12590
+ * lever without a `category` grant (a `category` grant also covers device
12591
+ * caps that carry no deviceId; `all` is specifically the device set).
12592
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
12593
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
12594
+ * is NOT covered until the grant is edited.
12595
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
12596
+ * DYNAMIC. A device that changes type, or a new device of the type,
12597
+ * re-resolves on the next request.
12598
+ * - `locations` — every device whose operator-assigned `location` label is
12599
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
12600
+ * null/unset location matches NO `locations` selector.
12601
+ */
12602
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
12603
+ object({ kind: literal("all") }),
12604
+ object({
12605
+ kind: literal("ids"),
12606
+ ids: array(number().int()).min(1)
12607
+ }),
12608
+ object({
12609
+ kind: literal("types"),
12610
+ types: array(_enum(DeviceType)).min(1)
12611
+ }),
12612
+ object({
12613
+ kind: literal("locations"),
12614
+ locations: array(string().min(1)).min(1)
12615
+ })
12616
+ ]);
12617
+ var DeviceTokenScopeSchema = object({
12618
+ type: literal("device"),
12619
+ /** The device SET this grant covers — resolved against the live fleet. */
12620
+ selector: DeviceSelectorSchema,
12621
+ access: array(MethodAccessSchema).min(1),
12622
+ /**
12623
+ * Whether a grant on a PARENT device transparently covers its accessory
12624
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
12625
+ * Direction is parent → children ONLY.
12626
+ *
12627
+ * Absent → the matcher DERIVES it from the access flavour: `view`
12628
+ * inherits (a camera viewer sees the camera's accessories), `create` /
12629
+ * `delete` do NOT (actuating/removing a child is an explicit act the
12630
+ * operator must grant on the child, not inherit from the parent). Set it
12631
+ * explicitly to override that default per grant.
12632
+ */
12633
+ includeLinked: boolean().optional()
12634
+ });
12635
+ /**
12636
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
12637
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
12638
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
12639
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
12640
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
12641
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
12642
+ * migration cannot reach a JWT already in a client's hands; parse-time
12643
+ * migration covers both without a flag day. No cast — the raw object is read
12644
+ * through `Reflect.get` (its static type is `unknown`).
12645
+ */
12646
+ function migrateLegacyTokenScope(raw) {
12647
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
12648
+ if (Reflect.get(raw, "type") !== "device") return raw;
12649
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
12650
+ const targets = Reflect.get(raw, "targets");
12651
+ if (!Array.isArray(targets)) return raw;
12652
+ return {
12653
+ type: "device",
12654
+ selector: {
12655
+ kind: "ids",
12656
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
12657
+ },
12658
+ access: Reflect.get(raw, "access")
12659
+ };
12660
+ }
12661
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
12662
+ object({
12663
+ type: literal("category"),
12664
+ target: CapScopeSchema,
12665
+ access: array(MethodAccessSchema).min(1)
12666
+ }),
12667
+ object({
12668
+ type: literal("capability"),
12669
+ target: string(),
12670
+ access: array(MethodAccessSchema).min(1)
12671
+ }),
12672
+ object({
12673
+ type: literal("addon"),
12674
+ target: string(),
12675
+ access: array(MethodAccessSchema).min(1)
12676
+ }),
12677
+ DeviceTokenScopeSchema
12678
+ ]));
12679
+ object({
12680
+ id: string(),
12681
+ username: string(),
12682
+ passwordHash: string(),
12683
+ /**
12684
+ * Admin bypass. When true, the middleware skips the scope-access
12685
+ * check entirely. There is no other axis of privilege; the legacy
12686
+ * role enum collapsed onto this boolean in v2.
12687
+ */
12688
+ isAdmin: boolean().default(false),
12689
+ allowedProviders: AllowedProviderSchema,
12690
+ allowedDevices: AllowedDevicesSchema,
12691
+ /**
12692
+ * Scopes granted to this user. Admins bypass; their `scopes` is
12693
+ * ignored. Non-admins without scopes are locked out of every
12694
+ * protected call.
12695
+ */
12696
+ scopes: array(TokenScopeSchema).default([]),
12697
+ createdAt: number(),
12698
+ updatedAt: number()
12699
+ });
12700
+ object({
12701
+ id: string(),
12702
+ label: string(),
12703
+ isAdmin: boolean().default(false),
12704
+ allowedProviders: AllowedProviderSchema,
12705
+ allowedDevices: AllowedDevicesSchema,
12706
+ tokenHash: string(),
12707
+ tokenPrefix: string(),
12708
+ createdAt: number(),
12709
+ lastUsedAt: number().optional()
12710
+ });
12711
+ object({
12712
+ id: string(),
12713
+ userId: string(),
12714
+ name: string(),
12715
+ tokenHash: string(),
12716
+ tokenPrefix: string(),
12717
+ scopes: array(TokenScopeSchema),
12718
+ expiresAt: number().nullish(),
12719
+ lastUsedAt: number().nullish(),
12720
+ createdAt: number()
12721
+ });
12722
+ /** What a share-view grant lets its holder see. */
12723
+ var ShareViewGrantSchema = object({
12724
+ kind: _enum(SHARE_VIEW_KINDS),
12725
+ deviceIds: array(number().int().nonnegative()).min(1).max(64),
12726
+ /** Talk-back, opt-in at mint time; absent means off. */
12727
+ talk: boolean().optional()
12728
+ });
12729
+ var ShareViewScopeSchema = object({
12730
+ type: literal("share-view"),
12731
+ grant: ShareViewGrantSchema
12732
+ });
12733
+ var AddonRoutesScopeSchema = object({
12734
+ type: literal("addon-routes"),
12735
+ access: array(MethodAccessSchema).min(1)
12736
+ });
12737
+ var CredentialScopeSchema = union([
12738
+ literal("*"),
12739
+ ShareViewScopeSchema,
12740
+ AddonRoutesScopeSchema,
12741
+ TokenScopeSchema
12742
+ ]);
12743
+ object({
12744
+ kind: literal("credential"),
12745
+ sub: string().min(1),
12746
+ jti: string().min(16),
12747
+ scopes: array(CredentialScopeSchema).min(1)
12748
+ });
12520
12749
  _enum(["new-session", "step-up"]);
12521
12750
  /** The languages the hub's app landing pages are written in (D858). */
12522
12751
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -44023,202 +44252,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
44023
44252
  auth: "admin"
44024
44253
  }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
44025
44254
  /**
44026
- * Zod schemas for persisted record types.
44027
- *
44028
- * These schemas serve as the single source of truth for types that are
44029
- * stored in the settings-store backend and retrieved via tRPC. They
44030
- * replace the manual TypeScript interfaces with schema-derived types,
44031
- * enabling runtime validation when reading from the backend.
44032
- *
44033
- * Convention: each schema is named `<Type>Schema`, the inferred TS type
44034
- * keeps the original name for backward compatibility.
44035
- */
44036
- /**
44037
- * Auth model (v2 — 2026-05-12 caps-only):
44038
- *
44039
- * Two principals:
44040
- * - `isAdmin: true` — full bypass. Admin scope set is ignored.
44041
- * - `isAdmin: false` — every call gated by `scopes` (see TokenScope).
44042
- *
44043
- * No role enum. There used to be `viewer / agent / scoped` and earlier
44044
- * `super_admin` — collapsed onto the single boolean because every
44045
- * non-admin caller is governed by the same scope-check rules; the
44046
- * distinction was only ever used to route role-specific procedures
44047
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
44048
- * with `isAdmin: false` + an explicit scope list.
44049
- */
44050
- /** Per-method access flavour. Materialised on every cap method via codegen. */
44051
- var MethodAccessSchema = _enum([
44052
- "view",
44053
- "create",
44054
- "delete"
44055
- ]);
44056
- /**
44057
- * A single scope grant. Three forms — checked in matcher with OR
44058
- * semantics; the first match decides whether the call passes:
44059
- *
44060
- * - `category` — broadest. `target: 'device' | 'system'` selects every
44061
- * cap with the matching `scope` declaration. New caps inherit grants
44062
- * automatically — adding a device cap to the codebase makes it
44063
- * reachable to every user with `category:device [...]` without a
44064
- * re-grant. Use this for "family viewer" / "operator" tiers.
44065
- *
44066
- * - `addon` — every cap that ships inside a given addon id. Niche;
44067
- * useful when an integration needs to interact with one specific
44068
- * addon's surface regardless of how many caps it exports.
44069
- *
44070
- * - `capability` — the most precise form. Single cap name. Use for
44071
- * integration tokens where you want to grant `addons.installPackage`
44072
- * and nothing else.
44073
- *
44074
- * `access` is REQUIRED with min 1 element. `admin` bypass is the
44075
- * "give me everything" escape; there is no wildcard scope.
44076
- */
44077
- var AllowedProviderSchema = union([literal("*"), array(string())]);
44078
- var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
44079
- var CapScopeSchema = _enum(["device", "system"]);
44080
- /**
44081
- * DeviceSelector (scope model v3 — 2026-08-12).
44082
- *
44083
- * A `device` grant no longer carries a frozen list of deviceIds. It carries
44084
- * a SELECTOR the matcher resolves against the live fleet, so the grant can be
44085
- * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
44086
- * AFTER the grant was minted — no re-grant, no re-login.
44087
- *
44088
- * - `all` — every device in the deployment. The broad viewer/operator
44089
- * lever without a `category` grant (a `category` grant also covers device
44090
- * caps that carry no deviceId; `all` is specifically the device set).
44091
- * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
44092
- * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
44093
- * is NOT covered until the grant is edited.
44094
- * - `types` — every device of a `DeviceType` (e.g. every `camera`).
44095
- * DYNAMIC. A device that changes type, or a new device of the type,
44096
- * re-resolves on the next request.
44097
- * - `locations` — every device whose operator-assigned `location` label is
44098
- * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
44099
- * null/unset location matches NO `locations` selector.
44100
- */
44101
- var DeviceSelectorSchema = discriminatedUnion("kind", [
44102
- object({ kind: literal("all") }),
44103
- object({
44104
- kind: literal("ids"),
44105
- ids: array(number().int()).min(1)
44106
- }),
44107
- object({
44108
- kind: literal("types"),
44109
- types: array(_enum(DeviceType)).min(1)
44110
- }),
44111
- object({
44112
- kind: literal("locations"),
44113
- locations: array(string().min(1)).min(1)
44114
- })
44115
- ]);
44116
- var DeviceTokenScopeSchema = object({
44117
- type: literal("device"),
44118
- /** The device SET this grant covers — resolved against the live fleet. */
44119
- selector: DeviceSelectorSchema,
44120
- access: array(MethodAccessSchema).min(1),
44121
- /**
44122
- * Whether a grant on a PARENT device transparently covers its accessory
44123
- * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
44124
- * Direction is parent → children ONLY.
44125
- *
44126
- * Absent → the matcher DERIVES it from the access flavour: `view`
44127
- * inherits (a camera viewer sees the camera's accessories), `create` /
44128
- * `delete` do NOT (actuating/removing a child is an explicit act the
44129
- * operator must grant on the child, not inherit from the parent). Set it
44130
- * explicitly to override that default per grant.
44131
- */
44132
- includeLinked: boolean().optional()
44133
- });
44134
- /**
44135
- * v2 → v3 lazy migration. A pre-v3 `device` grant carried
44136
- * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
44137
- * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
44138
- * EVERY parse path — stored records AND the JWT-carried scope arrays
44139
- * normalised at the request boundary ({@link normalizeTokenScopes} in
44140
- * `device-selector.ts`). Chosen over a one-time DB migration because a
44141
- * migration cannot reach a JWT already in a client's hands; parse-time
44142
- * migration covers both without a flag day. No cast — the raw object is read
44143
- * through `Reflect.get` (its static type is `unknown`).
44144
- */
44145
- function migrateLegacyTokenScope(raw) {
44146
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
44147
- if (Reflect.get(raw, "type") !== "device") return raw;
44148
- if (Reflect.get(raw, "selector") !== void 0) return raw;
44149
- const targets = Reflect.get(raw, "targets");
44150
- if (!Array.isArray(targets)) return raw;
44151
- return {
44152
- type: "device",
44153
- selector: {
44154
- kind: "ids",
44155
- ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
44156
- },
44157
- access: Reflect.get(raw, "access")
44158
- };
44159
- }
44160
- var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
44161
- object({
44162
- type: literal("category"),
44163
- target: CapScopeSchema,
44164
- access: array(MethodAccessSchema).min(1)
44165
- }),
44166
- object({
44167
- type: literal("capability"),
44168
- target: string(),
44169
- access: array(MethodAccessSchema).min(1)
44170
- }),
44171
- object({
44172
- type: literal("addon"),
44173
- target: string(),
44174
- access: array(MethodAccessSchema).min(1)
44175
- }),
44176
- DeviceTokenScopeSchema
44177
- ]));
44178
- object({
44179
- id: string(),
44180
- username: string(),
44181
- passwordHash: string(),
44182
- /**
44183
- * Admin bypass. When true, the middleware skips the scope-access
44184
- * check entirely. There is no other axis of privilege; the legacy
44185
- * role enum collapsed onto this boolean in v2.
44186
- */
44187
- isAdmin: boolean().default(false),
44188
- allowedProviders: AllowedProviderSchema,
44189
- allowedDevices: AllowedDevicesSchema,
44190
- /**
44191
- * Scopes granted to this user. Admins bypass; their `scopes` is
44192
- * ignored. Non-admins without scopes are locked out of every
44193
- * protected call.
44194
- */
44195
- scopes: array(TokenScopeSchema).default([]),
44196
- createdAt: number(),
44197
- updatedAt: number()
44198
- });
44199
- object({
44200
- id: string(),
44201
- label: string(),
44202
- isAdmin: boolean().default(false),
44203
- allowedProviders: AllowedProviderSchema,
44204
- allowedDevices: AllowedDevicesSchema,
44205
- tokenHash: string(),
44206
- tokenPrefix: string(),
44207
- createdAt: number(),
44208
- lastUsedAt: number().optional()
44209
- });
44210
- object({
44211
- id: string(),
44212
- userId: string(),
44213
- name: string(),
44214
- tokenHash: string(),
44215
- tokenPrefix: string(),
44216
- scopes: array(TokenScopeSchema),
44217
- expiresAt: number().nullish(),
44218
- lastUsedAt: number().nullish(),
44219
- createdAt: number()
44220
- });
44221
- /**
44222
44255
  * `oauth-integration` — a collection cap by which an addon declares
44223
44256
  * itself a linkable OAuth client of the hub's core `/oauth2/*` server.
44224
44257
  * Each provider returns a static descriptor; the core enumerates them
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreame",
3
- "version": "0.2.136",
3
+ "version": "0.2.137",
4
4
  "description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
5
5
  "keywords": [
6
6
  "camstack",