@camstack/addon-provider-velux 0.2.121 → 0.2.123

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 +267 -11
  2. package/dist/addon.mjs +267 -11
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5370,7 +5370,7 @@ var ZodIssueCode = {
5370
5370
  var ZodFirstPartyTypeKind;
5371
5371
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5372
5372
  //#endregion
5373
- //#region ../types/dist/sleep-BNeXenvr.mjs
5373
+ //#region ../types/dist/sleep-B0JG7-_F.mjs
5374
5374
  /**
5375
5375
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5376
5376
  * window to float samples (D455).
@@ -15192,6 +15192,10 @@ var DeviceInfoSchema = object({
15192
15192
  isCamera: boolean(),
15193
15193
  /** Current config values — serializable snapshot */
15194
15194
  config: record(string(), unknown()),
15195
+ /** Paths inside `config` the device's schema declares secret (D783) —
15196
+ * what the non-admin redaction withholds. Paths, never values. Absent
15197
+ * when the owning runner has not reported them. */
15198
+ secretConfigPaths: array(string()).optional(),
15195
15199
  /** Hardware + identity blob (manufacturer / model / firmware / sn /
15196
15200
  * uid / mac / …). Populated by drivers; editable via setMetadata. */
15197
15201
  metadata: record(string(), unknown()).nullable().optional(),
@@ -15397,7 +15401,13 @@ var DeviceRegisterPayloadSchema = object({
15397
15401
  * call (workers re-register on init), so probe-driven updates
15398
15402
  * (e.g. PTZ flag flipping after the abilities probe) propagate. */
15399
15403
  features: array(string()).optional(),
15400
- config: record(string(), unknown())
15404
+ config: record(string(), unknown()),
15405
+ /** Config paths the device's own schema DECLARES secret
15406
+ * (`.meta({ secret: true })` — dotted, `[]` for array items, e.g.
15407
+ * `connection.password`). Re-published on every register; the non-admin
15408
+ * redaction withholds them at any depth (D783). Optional: an older runner
15409
+ * omits it and the keyword backstop applies. */
15410
+ secretConfigPaths: array(string()).optional()
15401
15411
  });
15402
15412
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
15403
15413
  var DevicePersistConfigPayloadSchema = object({
@@ -17056,7 +17066,14 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
17056
17066
  icon: string().optional(),
17057
17067
  /** Addon-owned HTTP route the button navigates to (GET). */
17058
17068
  startUrl: string(),
17059
- stage: LoginStageEnum
17069
+ stage: LoginStageEnum,
17070
+ /**
17071
+ * The provider names an external identity a signed-in user can link to
17072
+ * their own account (D782): `auth.listLinkableProviders` /
17073
+ * `beginExternalLink` offer exactly the redirect methods that set this,
17074
+ * whatever their id. Absent / false — a login button only (magic-link).
17075
+ */
17076
+ linkable: boolean().optional()
17060
17077
  }),
17061
17078
  object({
17062
17079
  kind: literal("widget"),
@@ -22491,7 +22508,13 @@ var RetrainFrameSchema = object({
22491
22508
  sizeBytes: number().int(),
22492
22509
  width: number().int(),
22493
22510
  height: number().int(),
22494
- copiedAt: number()
22511
+ copiedAt: number(),
22512
+ /** When the CAMERA captured the frame. Absent on a copy taken before D785. */
22513
+ capturedAt: number().optional(),
22514
+ /** The operator's "every subject in this frame is boxed". Detector
22515
+ * evaluation keeps only complete frames: an unboxed subject would count as
22516
+ * a false positive. */
22517
+ complete: boolean()
22495
22518
  });
22496
22519
  /** Why a copy-on-select could not be honoured — named, never a silent skip. */
22497
22520
  var RetrainCopyRefusalSchema = _enum([
@@ -22512,6 +22535,51 @@ var RetrainFrameListSchema = object({
22512
22535
  /** What the page pre-selects — the native key frame when one survives. */
22513
22536
  autoPickMediaId: number().int().optional()
22514
22537
  });
22538
+ /**
22539
+ * Which frames an annotated export carries. Every field narrows; an empty
22540
+ * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
22541
+ * list owned by whoever trains (the training orchestrator), so `frameIds` is
22542
+ * the primitive a version export uses; `batchId` re-selects what an earlier
22543
+ * export carried (`exportedInBatch`).
22544
+ */
22545
+ var RetrainExportFilterSchema = object({
22546
+ deviceIds: array(number()).optional(),
22547
+ frameIds: array(string()).max(2e4).optional(),
22548
+ batchId: string().optional(),
22549
+ /** Only frames the operator marked complete (all subjects boxed). */
22550
+ completeOnly: boolean().optional()
22551
+ });
22552
+ /**
22553
+ * `frames`: the full frame copies, boxes in `annotations.json`.
22554
+ * `crops`: additionally one JPEG per subject, cut with the runtime detail-crop
22555
+ * convention — the classifier layout.
22556
+ */
22557
+ var RetrainExportLayoutSchema = _enum(["frames", "crops"]);
22558
+ /**
22559
+ * Where `writeRetrainArchive` streams the tar: one HTTP request whose body is
22560
+ * the archive, sent chunk by chunk. Covers a presigned PUT and a provider
22561
+ * addon's data-plane upload route alike. Headers are sent verbatim and never
22562
+ * logged.
22563
+ */
22564
+ var RetrainArchiveTargetSchema = object({
22565
+ kind: literal("http"),
22566
+ method: _enum(["PUT", "POST"]),
22567
+ url: string().url(),
22568
+ headers: record(string(), string()).optional()
22569
+ });
22570
+ var RetrainArchiveResultSchema = object({
22571
+ batchId: string(),
22572
+ frames: number().int(),
22573
+ crops: number().int(),
22574
+ annotations: number().int(),
22575
+ /** Frames planned but not shipped (unreadable copy, path too long). */
22576
+ missing: number().int(),
22577
+ bytes: number().int(),
22578
+ /** sha256 of the exact bytes sent. */
22579
+ sha256: string(),
22580
+ /** The target's HTTP status. */
22581
+ status: number().int()
22582
+ });
22515
22583
  /** What the operator asked the assist to look for. */
22516
22584
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
22517
22585
  kind: literal("package"),
@@ -23306,9 +23374,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
23306
23374
  }), RetrainTransitionResultSchema, {
23307
23375
  kind: "mutation",
23308
23376
  auth: "admin"
23309
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
23377
+ }), method(RetrainExportFilterSchema.extend({ layout: RetrainExportLayoutSchema.optional() }), object({ url: string() }), {
23310
23378
  kind: "query",
23311
23379
  auth: "admin"
23380
+ }), method(object({
23381
+ deviceId: number(),
23382
+ trackId: string(),
23383
+ frameId: string(),
23384
+ complete: boolean()
23385
+ }), RetrainFrameSchema, {
23386
+ kind: "mutation",
23387
+ auth: "admin"
23388
+ }), method(object({
23389
+ filter: RetrainExportFilterSchema,
23390
+ layout: RetrainExportLayoutSchema,
23391
+ target: RetrainArchiveTargetSchema
23392
+ }), RetrainArchiveResultSchema, {
23393
+ kind: "mutation",
23394
+ auth: "admin",
23395
+ timeoutMs: 60 * 6e4
23312
23396
  }), method(object({
23313
23397
  /** Which of the three event tables owns the row. */
23314
23398
  ownerType: EventOwnerTypeSchema,
@@ -26638,7 +26722,19 @@ var SsoBridgeClaimsSchema = object({
26638
26722
  * editing a descriptor must not retroactively extend or shorten a link the
26639
26723
  * operator already consented to.
26640
26724
  */
26641
- refreshTtl: union([number().int().positive(), literal("never")]).optional()
26725
+ refreshTtl: union([number().int().positive(), literal("never")]).optional(),
26726
+ /**
26727
+ * Opaque handle of a hub-side LINK intent (D782). Set by an OIDC callback
26728
+ * that was started from a signed-in user's "Link" button: the finish then
26729
+ * links this identity to the intent's user instead of signing anyone in.
26730
+ * The handle carries no user id — the hub resolves it, single-use.
26731
+ */
26732
+ linkIntent: string().optional(),
26733
+ /**
26734
+ * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
26735
+ * subject is unique only per issuer, so a link is bound to it.
26736
+ */
26737
+ issuer: string().optional()
26642
26738
  });
26643
26739
  method(object({
26644
26740
  claims: SsoBridgeClaimsSchema,
@@ -28573,7 +28669,22 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
28573
28669
  * field their hints were silently stripped by the schema and the
28574
28670
  * adaptive ladder started blind on the client's display size.
28575
28671
  */
28576
- hints: webrtcClientHintsSchema.optional()
28672
+ hints: webrtcClientHintsSchema.optional(),
28673
+ /**
28674
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
28675
+ * through the `intercom` cap's push-talk triple. When `true` and the
28676
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
28677
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
28678
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
28679
+ *
28680
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
28681
+ * with `intercom`, when the linked user may control that camera. The
28682
+ * hub STRIPS it from every request-bound call (a browser), exactly as
28683
+ * it overwrites `relayOnly` — a viewer's talk permission is the
28684
+ * intercom cap's own surface (share tokens gate it there), and this
28685
+ * flag must not become a second door to the camera's speaker.
28686
+ */
28687
+ talkback: boolean().optional()
28577
28688
  }), object({
28578
28689
  sessionId: string(),
28579
28690
  sdpAnswer: string()
@@ -28875,6 +28986,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
28875
28986
  var RestartAddonResultSchema = unknown();
28876
28987
  var InstallPackageResultSchema = unknown();
28877
28988
  var ReloadPackagesResultSchema = unknown();
28989
+ /**
28990
+ * What an uninstall did on ONE node.
28991
+ * - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
28992
+ * - `not-installed` — the node did not have it (nothing to do).
28993
+ * - `refused` — protected / bootstrap package; nothing touched.
28994
+ * - `failed` — attempted and did not complete; `error` says why.
28995
+ * - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
28996
+ * back-fill never returns the package, and the stale-addon sweep removes the
28997
+ * copy when the node registers again (only once the hub no longer has it).
28998
+ */
28999
+ var UninstallNodeOutcomeSchema = _enum([
29000
+ "uninstalled",
29001
+ "not-installed",
29002
+ "refused",
29003
+ "failed",
29004
+ "pending-reconnect"
29005
+ ]);
29006
+ var UninstallNodeResultSchema = object({
29007
+ nodeId: string(),
29008
+ outcome: UninstallNodeOutcomeSchema,
29009
+ error: string().optional(),
29010
+ addonIds: array(string()).readonly(),
29011
+ runnersStopped: array(string()).readonly(),
29012
+ warnings: array(string()).readonly()
29013
+ });
29014
+ var UninstallPackageResultSchema = object({
29015
+ /** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
29016
+ success: boolean(),
29017
+ packageName: string(),
29018
+ results: array(UninstallNodeResultSchema).readonly()
29019
+ });
29020
+ /**
29021
+ * `unreachable` lists online agents whose status read FAILED — absence from
29022
+ * `installations` is only "not installed" for a node that answered (D315).
29023
+ */
29024
+ var PackageInstallationsSchema = object({
29025
+ installations: array(object({
29026
+ packageName: string(),
29027
+ nodeId: string(),
29028
+ nodeName: string(),
29029
+ isHub: boolean(),
29030
+ isOnline: boolean(),
29031
+ version: string().nullable(),
29032
+ addonIds: array(string()).readonly(),
29033
+ source: _enum(["live", "recorded"]),
29034
+ /** The hub installs this package too. `false` on an agent row = an orphan. */
29035
+ onHub: boolean()
29036
+ })).readonly(),
29037
+ unreachable: array(object({
29038
+ nodeId: string(),
29039
+ error: string()
29040
+ })).readonly()
29041
+ });
28878
29042
  var BulkUpdateItemStatusSchema = _enum([
28879
29043
  "queued",
28880
29044
  "updating",
@@ -28957,10 +29121,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
28957
29121
  }), method(object({ packageName: string() }), InstallPackageResultSchema, {
28958
29122
  kind: "mutation",
28959
29123
  auth: "admin"
28960
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({ packageName: string() }), unknown(), {
29124
+ }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
29125
+ packageName: string().min(1),
29126
+ nodeId: string().optional(),
29127
+ everywhere: boolean().optional()
29128
+ }), UninstallPackageResultSchema, {
28961
29129
  kind: "mutation",
28962
29130
  auth: "admin"
28963
- }), method(_void(), ReloadPackagesResultSchema, {
29131
+ }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
28964
29132
  kind: "mutation",
28965
29133
  auth: "admin"
28966
29134
  }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
@@ -38870,6 +39038,32 @@ var TotpStatusSchema = object({
38870
39038
  /** Null when no row exists OR the row is still pending confirmation. */
38871
39039
  confirmedAt: number().nullable()
38872
39040
  });
39041
+ /**
39042
+ * user-management — singleton capability for user accounts, API keys,
39043
+ * and scoped tokens.
39044
+ *
39045
+ * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
39046
+ * — the subset check on `setUserScopes` / `createScopedToken` is moot
39047
+ * because non-admins never reach these. If/when we open non-admin
39048
+ * delegation, structural caller-scope subset check goes inside the
39049
+ * provider.
39050
+ */
39051
+ var ExternalIdentitySchema = object({
39052
+ /** Login-method id of the provider instance, e.g. `auth-oidc/authentik`. */
39053
+ provider: string(),
39054
+ /** The IdP's stable subject (`sub`) for this account. */
39055
+ subject: string(),
39056
+ /** The verified `iss` of the IdP the identity was linked under — `sub` is unique only per issuer. */
39057
+ issuer: string(),
39058
+ userId: string(),
39059
+ /** What the IdP called the account at link time (username / email) — display only. */
39060
+ label: string().optional(),
39061
+ linkedAt: number()
39062
+ });
39063
+ var ExternalIdentityKeySchema = object({
39064
+ provider: string().min(1),
39065
+ subject: string().min(1)
39066
+ });
38873
39067
  method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
38874
39068
  kind: "mutation",
38875
39069
  auth: "admin",
@@ -38983,7 +39177,22 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
38983
39177
  userId: string(),
38984
39178
  username: string(),
38985
39179
  scopes: array(TokenScopeSchema)
38986
- }).nullable(), { access: "view" }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
39180
+ }).nullable(), { access: "view" }), method(object({ userId: string() }), array(ExternalIdentitySchema), { auth: "admin" }), method(ExternalIdentityKeySchema, object({
39181
+ userId: string(),
39182
+ issuer: string()
39183
+ }).nullable(), { auth: "admin" }), method(ExternalIdentityKeySchema.extend({
39184
+ userId: string(),
39185
+ issuer: string().min(1),
39186
+ label: string().optional()
39187
+ }), object({ success: literal(true) }), {
39188
+ kind: "mutation",
39189
+ auth: "admin",
39190
+ access: "create"
39191
+ }), method(ExternalIdentityKeySchema.extend({ userId: string() }), object({ success: boolean() }), {
39192
+ kind: "mutation",
39193
+ auth: "admin",
39194
+ access: "delete"
39195
+ }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
38987
39196
  kind: "mutation",
38988
39197
  auth: "admin",
38989
39198
  access: "delete"
@@ -41393,6 +41602,12 @@ Object.freeze({
41393
41602
  addonId: null,
41394
41603
  access: "view"
41395
41604
  },
41605
+ "addons.listInstallations": {
41606
+ capName: "addons",
41607
+ capScope: "system",
41608
+ addonId: null,
41609
+ access: "view"
41610
+ },
41396
41611
  "addons.listJobs": {
41397
41612
  capName: "addons",
41398
41613
  capScope: "system",
@@ -45617,6 +45832,12 @@ Object.freeze({
45617
45832
  addonId: null,
45618
45833
  access: "create"
45619
45834
  },
45835
+ "pipelineAnalytics.setRetrainFrameComplete": {
45836
+ capName: "pipeline-analytics",
45837
+ capScope: "device",
45838
+ addonId: null,
45839
+ access: "create"
45840
+ },
45620
45841
  "pipelineAnalytics.setTrackFlags": {
45621
45842
  capName: "pipeline-analytics",
45622
45843
  capScope: "device",
@@ -45653,6 +45874,12 @@ Object.freeze({
45653
45874
  addonId: null,
45654
45875
  access: "delete"
45655
45876
  },
45877
+ "pipelineAnalytics.writeRetrainArchive": {
45878
+ capName: "pipeline-analytics",
45879
+ capScope: "device",
45880
+ addonId: null,
45881
+ access: "create"
45882
+ },
45656
45883
  "pipelineExecutor.cacheFrameInPool": {
45657
45884
  capName: "pipeline-executor",
45658
45885
  capScope: "system",
@@ -48005,18 +48232,36 @@ Object.freeze({
48005
48232
  addonId: null,
48006
48233
  access: "delete"
48007
48234
  },
48235
+ "userManagement.findUserByExternalIdentity": {
48236
+ capName: "user-management",
48237
+ capScope: "system",
48238
+ addonId: null,
48239
+ access: "view"
48240
+ },
48008
48241
  "userManagement.getTotpStatus": {
48009
48242
  capName: "user-management",
48010
48243
  capScope: "system",
48011
48244
  addonId: null,
48012
48245
  access: "view"
48013
48246
  },
48247
+ "userManagement.linkExternalIdentity": {
48248
+ capName: "user-management",
48249
+ capScope: "system",
48250
+ addonId: null,
48251
+ access: "create"
48252
+ },
48014
48253
  "userManagement.listApiKeys": {
48015
48254
  capName: "user-management",
48016
48255
  capScope: "system",
48017
48256
  addonId: null,
48018
48257
  access: "view"
48019
48258
  },
48259
+ "userManagement.listExternalIdentities": {
48260
+ capName: "user-management",
48261
+ capScope: "system",
48262
+ addonId: null,
48263
+ access: "view"
48264
+ },
48020
48265
  "userManagement.listOauthSessions": {
48021
48266
  capName: "user-management",
48022
48267
  capScope: "system",
@@ -48095,6 +48340,12 @@ Object.freeze({
48095
48340
  addonId: null,
48096
48341
  access: "create"
48097
48342
  },
48343
+ "userManagement.unlinkExternalIdentity": {
48344
+ capName: "user-management",
48345
+ capScope: "system",
48346
+ addonId: null,
48347
+ access: "delete"
48348
+ },
48098
48349
  "userManagement.updateUser": {
48099
48350
  capName: "user-management",
48100
48351
  capScope: "system",
@@ -51434,6 +51685,11 @@ Object.freeze({
51434
51685
  form: "single",
51435
51686
  optional: false
51436
51687
  }],
51688
+ "pipelineAnalytics.setRetrainFrameComplete": [{
51689
+ name: "deviceId",
51690
+ form: "single",
51691
+ optional: false
51692
+ }],
51437
51693
  "pipelineAnalytics.setTrackFlags": [{
51438
51694
  name: "deviceId",
51439
51695
  form: "single",
@@ -53496,7 +53752,7 @@ var MB = 1024 * 1024;
53496
53752
  */
53497
53753
  var veluxConnectionSchema = object({
53498
53754
  host: string().min(1).describe("KLF-200 host name or IP address"),
53499
- password: string().default("").describe("KLF-200 WiFi/web password (printed on the back of the unit)"),
53755
+ password: string().default("").describe("KLF-200 WiFi/web password (printed on the back of the unit)").meta({ secret: true }),
53500
53756
  pollIntervalMs: preprocess((v) => v === "" || v === null ? void 0 : v, number().int().min(2e3).max(36e5).default(3e4)).describe("Node-state poll interval (ms)")
53501
53757
  });
53502
53758
  /**
package/dist/addon.mjs CHANGED
@@ -5369,7 +5369,7 @@ var ZodIssueCode = {
5369
5369
  var ZodFirstPartyTypeKind;
5370
5370
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5371
5371
  //#endregion
5372
- //#region ../types/dist/sleep-BNeXenvr.mjs
5372
+ //#region ../types/dist/sleep-B0JG7-_F.mjs
5373
5373
  /**
5374
5374
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5375
5375
  * window to float samples (D455).
@@ -15191,6 +15191,10 @@ var DeviceInfoSchema = object({
15191
15191
  isCamera: boolean(),
15192
15192
  /** Current config values — serializable snapshot */
15193
15193
  config: record(string(), unknown()),
15194
+ /** Paths inside `config` the device's schema declares secret (D783) —
15195
+ * what the non-admin redaction withholds. Paths, never values. Absent
15196
+ * when the owning runner has not reported them. */
15197
+ secretConfigPaths: array(string()).optional(),
15194
15198
  /** Hardware + identity blob (manufacturer / model / firmware / sn /
15195
15199
  * uid / mac / …). Populated by drivers; editable via setMetadata. */
15196
15200
  metadata: record(string(), unknown()).nullable().optional(),
@@ -15396,7 +15400,13 @@ var DeviceRegisterPayloadSchema = object({
15396
15400
  * call (workers re-register on init), so probe-driven updates
15397
15401
  * (e.g. PTZ flag flipping after the abilities probe) propagate. */
15398
15402
  features: array(string()).optional(),
15399
- config: record(string(), unknown())
15403
+ config: record(string(), unknown()),
15404
+ /** Config paths the device's own schema DECLARES secret
15405
+ * (`.meta({ secret: true })` — dotted, `[]` for array items, e.g.
15406
+ * `connection.password`). Re-published on every register; the non-admin
15407
+ * redaction withholds them at any depth (D783). Optional: an older runner
15408
+ * omits it and the keyword backstop applies. */
15409
+ secretConfigPaths: array(string()).optional()
15400
15410
  });
15401
15411
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
15402
15412
  var DevicePersistConfigPayloadSchema = object({
@@ -17055,7 +17065,14 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
17055
17065
  icon: string().optional(),
17056
17066
  /** Addon-owned HTTP route the button navigates to (GET). */
17057
17067
  startUrl: string(),
17058
- stage: LoginStageEnum
17068
+ stage: LoginStageEnum,
17069
+ /**
17070
+ * The provider names an external identity a signed-in user can link to
17071
+ * their own account (D782): `auth.listLinkableProviders` /
17072
+ * `beginExternalLink` offer exactly the redirect methods that set this,
17073
+ * whatever their id. Absent / false — a login button only (magic-link).
17074
+ */
17075
+ linkable: boolean().optional()
17059
17076
  }),
17060
17077
  object({
17061
17078
  kind: literal("widget"),
@@ -22490,7 +22507,13 @@ var RetrainFrameSchema = object({
22490
22507
  sizeBytes: number().int(),
22491
22508
  width: number().int(),
22492
22509
  height: number().int(),
22493
- copiedAt: number()
22510
+ copiedAt: number(),
22511
+ /** When the CAMERA captured the frame. Absent on a copy taken before D785. */
22512
+ capturedAt: number().optional(),
22513
+ /** The operator's "every subject in this frame is boxed". Detector
22514
+ * evaluation keeps only complete frames: an unboxed subject would count as
22515
+ * a false positive. */
22516
+ complete: boolean()
22494
22517
  });
22495
22518
  /** Why a copy-on-select could not be honoured — named, never a silent skip. */
22496
22519
  var RetrainCopyRefusalSchema = _enum([
@@ -22511,6 +22534,51 @@ var RetrainFrameListSchema = object({
22511
22534
  /** What the page pre-selects — the native key frame when one survives. */
22512
22535
  autoPickMediaId: number().int().optional()
22513
22536
  });
22537
+ /**
22538
+ * Which frames an annotated export carries. Every field narrows; an empty
22539
+ * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
22540
+ * list owned by whoever trains (the training orchestrator), so `frameIds` is
22541
+ * the primitive a version export uses; `batchId` re-selects what an earlier
22542
+ * export carried (`exportedInBatch`).
22543
+ */
22544
+ var RetrainExportFilterSchema = object({
22545
+ deviceIds: array(number()).optional(),
22546
+ frameIds: array(string()).max(2e4).optional(),
22547
+ batchId: string().optional(),
22548
+ /** Only frames the operator marked complete (all subjects boxed). */
22549
+ completeOnly: boolean().optional()
22550
+ });
22551
+ /**
22552
+ * `frames`: the full frame copies, boxes in `annotations.json`.
22553
+ * `crops`: additionally one JPEG per subject, cut with the runtime detail-crop
22554
+ * convention — the classifier layout.
22555
+ */
22556
+ var RetrainExportLayoutSchema = _enum(["frames", "crops"]);
22557
+ /**
22558
+ * Where `writeRetrainArchive` streams the tar: one HTTP request whose body is
22559
+ * the archive, sent chunk by chunk. Covers a presigned PUT and a provider
22560
+ * addon's data-plane upload route alike. Headers are sent verbatim and never
22561
+ * logged.
22562
+ */
22563
+ var RetrainArchiveTargetSchema = object({
22564
+ kind: literal("http"),
22565
+ method: _enum(["PUT", "POST"]),
22566
+ url: string().url(),
22567
+ headers: record(string(), string()).optional()
22568
+ });
22569
+ var RetrainArchiveResultSchema = object({
22570
+ batchId: string(),
22571
+ frames: number().int(),
22572
+ crops: number().int(),
22573
+ annotations: number().int(),
22574
+ /** Frames planned but not shipped (unreadable copy, path too long). */
22575
+ missing: number().int(),
22576
+ bytes: number().int(),
22577
+ /** sha256 of the exact bytes sent. */
22578
+ sha256: string(),
22579
+ /** The target's HTTP status. */
22580
+ status: number().int()
22581
+ });
22514
22582
  /** What the operator asked the assist to look for. */
22515
22583
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
22516
22584
  kind: literal("package"),
@@ -23305,9 +23373,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
23305
23373
  }), RetrainTransitionResultSchema, {
23306
23374
  kind: "mutation",
23307
23375
  auth: "admin"
23308
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
23376
+ }), method(RetrainExportFilterSchema.extend({ layout: RetrainExportLayoutSchema.optional() }), object({ url: string() }), {
23309
23377
  kind: "query",
23310
23378
  auth: "admin"
23379
+ }), method(object({
23380
+ deviceId: number(),
23381
+ trackId: string(),
23382
+ frameId: string(),
23383
+ complete: boolean()
23384
+ }), RetrainFrameSchema, {
23385
+ kind: "mutation",
23386
+ auth: "admin"
23387
+ }), method(object({
23388
+ filter: RetrainExportFilterSchema,
23389
+ layout: RetrainExportLayoutSchema,
23390
+ target: RetrainArchiveTargetSchema
23391
+ }), RetrainArchiveResultSchema, {
23392
+ kind: "mutation",
23393
+ auth: "admin",
23394
+ timeoutMs: 60 * 6e4
23311
23395
  }), method(object({
23312
23396
  /** Which of the three event tables owns the row. */
23313
23397
  ownerType: EventOwnerTypeSchema,
@@ -26637,7 +26721,19 @@ var SsoBridgeClaimsSchema = object({
26637
26721
  * editing a descriptor must not retroactively extend or shorten a link the
26638
26722
  * operator already consented to.
26639
26723
  */
26640
- refreshTtl: union([number().int().positive(), literal("never")]).optional()
26724
+ refreshTtl: union([number().int().positive(), literal("never")]).optional(),
26725
+ /**
26726
+ * Opaque handle of a hub-side LINK intent (D782). Set by an OIDC callback
26727
+ * that was started from a signed-in user's "Link" button: the finish then
26728
+ * links this identity to the intent's user instead of signing anyone in.
26729
+ * The handle carries no user id — the hub resolves it, single-use.
26730
+ */
26731
+ linkIntent: string().optional(),
26732
+ /**
26733
+ * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
26734
+ * subject is unique only per issuer, so a link is bound to it.
26735
+ */
26736
+ issuer: string().optional()
26641
26737
  });
26642
26738
  method(object({
26643
26739
  claims: SsoBridgeClaimsSchema,
@@ -28572,7 +28668,22 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
28572
28668
  * field their hints were silently stripped by the schema and the
28573
28669
  * adaptive ladder started blind on the client's display size.
28574
28670
  */
28575
- hints: webrtcClientHintsSchema.optional()
28671
+ hints: webrtcClientHintsSchema.optional(),
28672
+ /**
28673
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
28674
+ * through the `intercom` cap's push-talk triple. When `true` and the
28675
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
28676
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
28677
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
28678
+ *
28679
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
28680
+ * with `intercom`, when the linked user may control that camera. The
28681
+ * hub STRIPS it from every request-bound call (a browser), exactly as
28682
+ * it overwrites `relayOnly` — a viewer's talk permission is the
28683
+ * intercom cap's own surface (share tokens gate it there), and this
28684
+ * flag must not become a second door to the camera's speaker.
28685
+ */
28686
+ talkback: boolean().optional()
28576
28687
  }), object({
28577
28688
  sessionId: string(),
28578
28689
  sdpAnswer: string()
@@ -28874,6 +28985,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
28874
28985
  var RestartAddonResultSchema = unknown();
28875
28986
  var InstallPackageResultSchema = unknown();
28876
28987
  var ReloadPackagesResultSchema = unknown();
28988
+ /**
28989
+ * What an uninstall did on ONE node.
28990
+ * - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
28991
+ * - `not-installed` — the node did not have it (nothing to do).
28992
+ * - `refused` — protected / bootstrap package; nothing touched.
28993
+ * - `failed` — attempted and did not complete; `error` says why.
28994
+ * - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
28995
+ * back-fill never returns the package, and the stale-addon sweep removes the
28996
+ * copy when the node registers again (only once the hub no longer has it).
28997
+ */
28998
+ var UninstallNodeOutcomeSchema = _enum([
28999
+ "uninstalled",
29000
+ "not-installed",
29001
+ "refused",
29002
+ "failed",
29003
+ "pending-reconnect"
29004
+ ]);
29005
+ var UninstallNodeResultSchema = object({
29006
+ nodeId: string(),
29007
+ outcome: UninstallNodeOutcomeSchema,
29008
+ error: string().optional(),
29009
+ addonIds: array(string()).readonly(),
29010
+ runnersStopped: array(string()).readonly(),
29011
+ warnings: array(string()).readonly()
29012
+ });
29013
+ var UninstallPackageResultSchema = object({
29014
+ /** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
29015
+ success: boolean(),
29016
+ packageName: string(),
29017
+ results: array(UninstallNodeResultSchema).readonly()
29018
+ });
29019
+ /**
29020
+ * `unreachable` lists online agents whose status read FAILED — absence from
29021
+ * `installations` is only "not installed" for a node that answered (D315).
29022
+ */
29023
+ var PackageInstallationsSchema = object({
29024
+ installations: array(object({
29025
+ packageName: string(),
29026
+ nodeId: string(),
29027
+ nodeName: string(),
29028
+ isHub: boolean(),
29029
+ isOnline: boolean(),
29030
+ version: string().nullable(),
29031
+ addonIds: array(string()).readonly(),
29032
+ source: _enum(["live", "recorded"]),
29033
+ /** The hub installs this package too. `false` on an agent row = an orphan. */
29034
+ onHub: boolean()
29035
+ })).readonly(),
29036
+ unreachable: array(object({
29037
+ nodeId: string(),
29038
+ error: string()
29039
+ })).readonly()
29040
+ });
28877
29041
  var BulkUpdateItemStatusSchema = _enum([
28878
29042
  "queued",
28879
29043
  "updating",
@@ -28956,10 +29120,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
28956
29120
  }), method(object({ packageName: string() }), InstallPackageResultSchema, {
28957
29121
  kind: "mutation",
28958
29122
  auth: "admin"
28959
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({ packageName: string() }), unknown(), {
29123
+ }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
29124
+ packageName: string().min(1),
29125
+ nodeId: string().optional(),
29126
+ everywhere: boolean().optional()
29127
+ }), UninstallPackageResultSchema, {
28960
29128
  kind: "mutation",
28961
29129
  auth: "admin"
28962
- }), method(_void(), ReloadPackagesResultSchema, {
29130
+ }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
28963
29131
  kind: "mutation",
28964
29132
  auth: "admin"
28965
29133
  }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
@@ -38869,6 +39037,32 @@ var TotpStatusSchema = object({
38869
39037
  /** Null when no row exists OR the row is still pending confirmation. */
38870
39038
  confirmedAt: number().nullable()
38871
39039
  });
39040
+ /**
39041
+ * user-management — singleton capability for user accounts, API keys,
39042
+ * and scoped tokens.
39043
+ *
39044
+ * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
39045
+ * — the subset check on `setUserScopes` / `createScopedToken` is moot
39046
+ * because non-admins never reach these. If/when we open non-admin
39047
+ * delegation, structural caller-scope subset check goes inside the
39048
+ * provider.
39049
+ */
39050
+ var ExternalIdentitySchema = object({
39051
+ /** Login-method id of the provider instance, e.g. `auth-oidc/authentik`. */
39052
+ provider: string(),
39053
+ /** The IdP's stable subject (`sub`) for this account. */
39054
+ subject: string(),
39055
+ /** The verified `iss` of the IdP the identity was linked under — `sub` is unique only per issuer. */
39056
+ issuer: string(),
39057
+ userId: string(),
39058
+ /** What the IdP called the account at link time (username / email) — display only. */
39059
+ label: string().optional(),
39060
+ linkedAt: number()
39061
+ });
39062
+ var ExternalIdentityKeySchema = object({
39063
+ provider: string().min(1),
39064
+ subject: string().min(1)
39065
+ });
38872
39066
  method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
38873
39067
  kind: "mutation",
38874
39068
  auth: "admin",
@@ -38982,7 +39176,22 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
38982
39176
  userId: string(),
38983
39177
  username: string(),
38984
39178
  scopes: array(TokenScopeSchema)
38985
- }).nullable(), { access: "view" }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
39179
+ }).nullable(), { access: "view" }), method(object({ userId: string() }), array(ExternalIdentitySchema), { auth: "admin" }), method(ExternalIdentityKeySchema, object({
39180
+ userId: string(),
39181
+ issuer: string()
39182
+ }).nullable(), { auth: "admin" }), method(ExternalIdentityKeySchema.extend({
39183
+ userId: string(),
39184
+ issuer: string().min(1),
39185
+ label: string().optional()
39186
+ }), object({ success: literal(true) }), {
39187
+ kind: "mutation",
39188
+ auth: "admin",
39189
+ access: "create"
39190
+ }), method(ExternalIdentityKeySchema.extend({ userId: string() }), object({ success: boolean() }), {
39191
+ kind: "mutation",
39192
+ auth: "admin",
39193
+ access: "delete"
39194
+ }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
38986
39195
  kind: "mutation",
38987
39196
  auth: "admin",
38988
39197
  access: "delete"
@@ -41392,6 +41601,12 @@ Object.freeze({
41392
41601
  addonId: null,
41393
41602
  access: "view"
41394
41603
  },
41604
+ "addons.listInstallations": {
41605
+ capName: "addons",
41606
+ capScope: "system",
41607
+ addonId: null,
41608
+ access: "view"
41609
+ },
41395
41610
  "addons.listJobs": {
41396
41611
  capName: "addons",
41397
41612
  capScope: "system",
@@ -45616,6 +45831,12 @@ Object.freeze({
45616
45831
  addonId: null,
45617
45832
  access: "create"
45618
45833
  },
45834
+ "pipelineAnalytics.setRetrainFrameComplete": {
45835
+ capName: "pipeline-analytics",
45836
+ capScope: "device",
45837
+ addonId: null,
45838
+ access: "create"
45839
+ },
45619
45840
  "pipelineAnalytics.setTrackFlags": {
45620
45841
  capName: "pipeline-analytics",
45621
45842
  capScope: "device",
@@ -45652,6 +45873,12 @@ Object.freeze({
45652
45873
  addonId: null,
45653
45874
  access: "delete"
45654
45875
  },
45876
+ "pipelineAnalytics.writeRetrainArchive": {
45877
+ capName: "pipeline-analytics",
45878
+ capScope: "device",
45879
+ addonId: null,
45880
+ access: "create"
45881
+ },
45655
45882
  "pipelineExecutor.cacheFrameInPool": {
45656
45883
  capName: "pipeline-executor",
45657
45884
  capScope: "system",
@@ -48004,18 +48231,36 @@ Object.freeze({
48004
48231
  addonId: null,
48005
48232
  access: "delete"
48006
48233
  },
48234
+ "userManagement.findUserByExternalIdentity": {
48235
+ capName: "user-management",
48236
+ capScope: "system",
48237
+ addonId: null,
48238
+ access: "view"
48239
+ },
48007
48240
  "userManagement.getTotpStatus": {
48008
48241
  capName: "user-management",
48009
48242
  capScope: "system",
48010
48243
  addonId: null,
48011
48244
  access: "view"
48012
48245
  },
48246
+ "userManagement.linkExternalIdentity": {
48247
+ capName: "user-management",
48248
+ capScope: "system",
48249
+ addonId: null,
48250
+ access: "create"
48251
+ },
48013
48252
  "userManagement.listApiKeys": {
48014
48253
  capName: "user-management",
48015
48254
  capScope: "system",
48016
48255
  addonId: null,
48017
48256
  access: "view"
48018
48257
  },
48258
+ "userManagement.listExternalIdentities": {
48259
+ capName: "user-management",
48260
+ capScope: "system",
48261
+ addonId: null,
48262
+ access: "view"
48263
+ },
48019
48264
  "userManagement.listOauthSessions": {
48020
48265
  capName: "user-management",
48021
48266
  capScope: "system",
@@ -48094,6 +48339,12 @@ Object.freeze({
48094
48339
  addonId: null,
48095
48340
  access: "create"
48096
48341
  },
48342
+ "userManagement.unlinkExternalIdentity": {
48343
+ capName: "user-management",
48344
+ capScope: "system",
48345
+ addonId: null,
48346
+ access: "delete"
48347
+ },
48097
48348
  "userManagement.updateUser": {
48098
48349
  capName: "user-management",
48099
48350
  capScope: "system",
@@ -51433,6 +51684,11 @@ Object.freeze({
51433
51684
  form: "single",
51434
51685
  optional: false
51435
51686
  }],
51687
+ "pipelineAnalytics.setRetrainFrameComplete": [{
51688
+ name: "deviceId",
51689
+ form: "single",
51690
+ optional: false
51691
+ }],
51436
51692
  "pipelineAnalytics.setTrackFlags": [{
51437
51693
  name: "deviceId",
51438
51694
  form: "single",
@@ -53495,7 +53751,7 @@ var MB = 1024 * 1024;
53495
53751
  */
53496
53752
  var veluxConnectionSchema = object({
53497
53753
  host: string().min(1).describe("KLF-200 host name or IP address"),
53498
- password: string().default("").describe("KLF-200 WiFi/web password (printed on the back of the unit)"),
53754
+ password: string().default("").describe("KLF-200 WiFi/web password (printed on the back of the unit)").meta({ secret: true }),
53499
53755
  pollIntervalMs: preprocess((v) => v === "" || v === null ? void 0 : v, number().int().min(2e3).max(36e5).default(3e4)).describe("Node-state poll interval (ms)")
53500
53756
  });
53501
53757
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-velux",
3
- "version": "0.2.121",
3
+ "version": "0.2.123",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",