@camstack/addon-provider-petkit 0.2.120 → 0.2.122

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
@@ -6472,7 +6472,7 @@ var ZodIssueCode = {
6472
6472
  var ZodFirstPartyTypeKind;
6473
6473
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6474
6474
  //#endregion
6475
- //#region ../types/dist/sleep-BNeXenvr.mjs
6475
+ //#region ../types/dist/sleep-B0JG7-_F.mjs
6476
6476
  /**
6477
6477
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6478
6478
  * window to float samples (D455).
@@ -16198,6 +16198,10 @@ var DeviceInfoSchema = object({
16198
16198
  isCamera: boolean(),
16199
16199
  /** Current config values — serializable snapshot */
16200
16200
  config: record(string(), unknown()),
16201
+ /** Paths inside `config` the device's schema declares secret (D783) —
16202
+ * what the non-admin redaction withholds. Paths, never values. Absent
16203
+ * when the owning runner has not reported them. */
16204
+ secretConfigPaths: array(string()).optional(),
16201
16205
  /** Hardware + identity blob (manufacturer / model / firmware / sn /
16202
16206
  * uid / mac / …). Populated by drivers; editable via setMetadata. */
16203
16207
  metadata: record(string(), unknown()).nullable().optional(),
@@ -16403,7 +16407,13 @@ var DeviceRegisterPayloadSchema = object({
16403
16407
  * call (workers re-register on init), so probe-driven updates
16404
16408
  * (e.g. PTZ flag flipping after the abilities probe) propagate. */
16405
16409
  features: array(string()).optional(),
16406
- config: record(string(), unknown())
16410
+ config: record(string(), unknown()),
16411
+ /** Config paths the device's own schema DECLARES secret
16412
+ * (`.meta({ secret: true })` — dotted, `[]` for array items, e.g.
16413
+ * `connection.password`). Re-published on every register; the non-admin
16414
+ * redaction withholds them at any depth (D783). Optional: an older runner
16415
+ * omits it and the keyword backstop applies. */
16416
+ secretConfigPaths: array(string()).optional()
16407
16417
  });
16408
16418
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
16409
16419
  var DevicePersistConfigPayloadSchema = object({
@@ -18062,7 +18072,14 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
18062
18072
  icon: string().optional(),
18063
18073
  /** Addon-owned HTTP route the button navigates to (GET). */
18064
18074
  startUrl: string(),
18065
- stage: LoginStageEnum
18075
+ stage: LoginStageEnum,
18076
+ /**
18077
+ * The provider names an external identity a signed-in user can link to
18078
+ * their own account (D782): `auth.listLinkableProviders` /
18079
+ * `beginExternalLink` offer exactly the redirect methods that set this,
18080
+ * whatever their id. Absent / false — a login button only (magic-link).
18081
+ */
18082
+ linkable: boolean().optional()
18066
18083
  }),
18067
18084
  object({
18068
18085
  kind: literal("widget"),
@@ -23497,7 +23514,13 @@ var RetrainFrameSchema = object({
23497
23514
  sizeBytes: number().int(),
23498
23515
  width: number().int(),
23499
23516
  height: number().int(),
23500
- copiedAt: number()
23517
+ copiedAt: number(),
23518
+ /** When the CAMERA captured the frame. Absent on a copy taken before D785. */
23519
+ capturedAt: number().optional(),
23520
+ /** The operator's "every subject in this frame is boxed". Detector
23521
+ * evaluation keeps only complete frames: an unboxed subject would count as
23522
+ * a false positive. */
23523
+ complete: boolean()
23501
23524
  });
23502
23525
  /** Why a copy-on-select could not be honoured — named, never a silent skip. */
23503
23526
  var RetrainCopyRefusalSchema = _enum([
@@ -23518,6 +23541,51 @@ var RetrainFrameListSchema = object({
23518
23541
  /** What the page pre-selects — the native key frame when one survives. */
23519
23542
  autoPickMediaId: number().int().optional()
23520
23543
  });
23544
+ /**
23545
+ * Which frames an annotated export carries. Every field narrows; an empty
23546
+ * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
23547
+ * list owned by whoever trains (the training orchestrator), so `frameIds` is
23548
+ * the primitive a version export uses; `batchId` re-selects what an earlier
23549
+ * export carried (`exportedInBatch`).
23550
+ */
23551
+ var RetrainExportFilterSchema = object({
23552
+ deviceIds: array(number()).optional(),
23553
+ frameIds: array(string()).max(2e4).optional(),
23554
+ batchId: string().optional(),
23555
+ /** Only frames the operator marked complete (all subjects boxed). */
23556
+ completeOnly: boolean().optional()
23557
+ });
23558
+ /**
23559
+ * `frames`: the full frame copies, boxes in `annotations.json`.
23560
+ * `crops`: additionally one JPEG per subject, cut with the runtime detail-crop
23561
+ * convention — the classifier layout.
23562
+ */
23563
+ var RetrainExportLayoutSchema = _enum(["frames", "crops"]);
23564
+ /**
23565
+ * Where `writeRetrainArchive` streams the tar: one HTTP request whose body is
23566
+ * the archive, sent chunk by chunk. Covers a presigned PUT and a provider
23567
+ * addon's data-plane upload route alike. Headers are sent verbatim and never
23568
+ * logged.
23569
+ */
23570
+ var RetrainArchiveTargetSchema = object({
23571
+ kind: literal("http"),
23572
+ method: _enum(["PUT", "POST"]),
23573
+ url: string().url(),
23574
+ headers: record(string(), string()).optional()
23575
+ });
23576
+ var RetrainArchiveResultSchema = object({
23577
+ batchId: string(),
23578
+ frames: number().int(),
23579
+ crops: number().int(),
23580
+ annotations: number().int(),
23581
+ /** Frames planned but not shipped (unreadable copy, path too long). */
23582
+ missing: number().int(),
23583
+ bytes: number().int(),
23584
+ /** sha256 of the exact bytes sent. */
23585
+ sha256: string(),
23586
+ /** The target's HTTP status. */
23587
+ status: number().int()
23588
+ });
23521
23589
  /** What the operator asked the assist to look for. */
23522
23590
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
23523
23591
  kind: literal("package"),
@@ -24312,9 +24380,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
24312
24380
  }), RetrainTransitionResultSchema, {
24313
24381
  kind: "mutation",
24314
24382
  auth: "admin"
24315
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
24383
+ }), method(RetrainExportFilterSchema.extend({ layout: RetrainExportLayoutSchema.optional() }), object({ url: string() }), {
24316
24384
  kind: "query",
24317
24385
  auth: "admin"
24386
+ }), method(object({
24387
+ deviceId: number(),
24388
+ trackId: string(),
24389
+ frameId: string(),
24390
+ complete: boolean()
24391
+ }), RetrainFrameSchema, {
24392
+ kind: "mutation",
24393
+ auth: "admin"
24394
+ }), method(object({
24395
+ filter: RetrainExportFilterSchema,
24396
+ layout: RetrainExportLayoutSchema,
24397
+ target: RetrainArchiveTargetSchema
24398
+ }), RetrainArchiveResultSchema, {
24399
+ kind: "mutation",
24400
+ auth: "admin",
24401
+ timeoutMs: 60 * 6e4
24318
24402
  }), method(object({
24319
24403
  /** Which of the three event tables owns the row. */
24320
24404
  ownerType: EventOwnerTypeSchema,
@@ -27644,7 +27728,19 @@ var SsoBridgeClaimsSchema = object({
27644
27728
  * editing a descriptor must not retroactively extend or shorten a link the
27645
27729
  * operator already consented to.
27646
27730
  */
27647
- refreshTtl: union([number().int().positive(), literal("never")]).optional()
27731
+ refreshTtl: union([number().int().positive(), literal("never")]).optional(),
27732
+ /**
27733
+ * Opaque handle of a hub-side LINK intent (D782). Set by an OIDC callback
27734
+ * that was started from a signed-in user's "Link" button: the finish then
27735
+ * links this identity to the intent's user instead of signing anyone in.
27736
+ * The handle carries no user id — the hub resolves it, single-use.
27737
+ */
27738
+ linkIntent: string().optional(),
27739
+ /**
27740
+ * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
27741
+ * subject is unique only per issuer, so a link is bound to it.
27742
+ */
27743
+ issuer: string().optional()
27648
27744
  });
27649
27745
  method(object({
27650
27746
  claims: SsoBridgeClaimsSchema,
@@ -29579,7 +29675,22 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
29579
29675
  * field their hints were silently stripped by the schema and the
29580
29676
  * adaptive ladder started blind on the client's display size.
29581
29677
  */
29582
- hints: webrtcClientHintsSchema.optional()
29678
+ hints: webrtcClientHintsSchema.optional(),
29679
+ /**
29680
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
29681
+ * through the `intercom` cap's push-talk triple. When `true` and the
29682
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
29683
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
29684
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
29685
+ *
29686
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
29687
+ * with `intercom`, when the linked user may control that camera. The
29688
+ * hub STRIPS it from every request-bound call (a browser), exactly as
29689
+ * it overwrites `relayOnly` — a viewer's talk permission is the
29690
+ * intercom cap's own surface (share tokens gate it there), and this
29691
+ * flag must not become a second door to the camera's speaker.
29692
+ */
29693
+ talkback: boolean().optional()
29583
29694
  }), object({
29584
29695
  sessionId: string(),
29585
29696
  sdpAnswer: string()
@@ -29881,6 +29992,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
29881
29992
  var RestartAddonResultSchema = unknown();
29882
29993
  var InstallPackageResultSchema = unknown();
29883
29994
  var ReloadPackagesResultSchema = unknown();
29995
+ /**
29996
+ * What an uninstall did on ONE node.
29997
+ * - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
29998
+ * - `not-installed` — the node did not have it (nothing to do).
29999
+ * - `refused` — protected / bootstrap package; nothing touched.
30000
+ * - `failed` — attempted and did not complete; `error` says why.
30001
+ * - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
30002
+ * back-fill never returns the package, and the stale-addon sweep removes the
30003
+ * copy when the node registers again (only once the hub no longer has it).
30004
+ */
30005
+ var UninstallNodeOutcomeSchema = _enum([
30006
+ "uninstalled",
30007
+ "not-installed",
30008
+ "refused",
30009
+ "failed",
30010
+ "pending-reconnect"
30011
+ ]);
30012
+ var UninstallNodeResultSchema = object({
30013
+ nodeId: string(),
30014
+ outcome: UninstallNodeOutcomeSchema,
30015
+ error: string().optional(),
30016
+ addonIds: array(string()).readonly(),
30017
+ runnersStopped: array(string()).readonly(),
30018
+ warnings: array(string()).readonly()
30019
+ });
30020
+ var UninstallPackageResultSchema = object({
30021
+ /** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
30022
+ success: boolean(),
30023
+ packageName: string(),
30024
+ results: array(UninstallNodeResultSchema).readonly()
30025
+ });
30026
+ /**
30027
+ * `unreachable` lists online agents whose status read FAILED — absence from
30028
+ * `installations` is only "not installed" for a node that answered (D315).
30029
+ */
30030
+ var PackageInstallationsSchema = object({
30031
+ installations: array(object({
30032
+ packageName: string(),
30033
+ nodeId: string(),
30034
+ nodeName: string(),
30035
+ isHub: boolean(),
30036
+ isOnline: boolean(),
30037
+ version: string().nullable(),
30038
+ addonIds: array(string()).readonly(),
30039
+ source: _enum(["live", "recorded"]),
30040
+ /** The hub installs this package too. `false` on an agent row = an orphan. */
30041
+ onHub: boolean()
30042
+ })).readonly(),
30043
+ unreachable: array(object({
30044
+ nodeId: string(),
30045
+ error: string()
30046
+ })).readonly()
30047
+ });
29884
30048
  var BulkUpdateItemStatusSchema = _enum([
29885
30049
  "queued",
29886
30050
  "updating",
@@ -29963,10 +30127,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
29963
30127
  }), method(object({ packageName: string() }), InstallPackageResultSchema, {
29964
30128
  kind: "mutation",
29965
30129
  auth: "admin"
29966
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({ packageName: string() }), unknown(), {
30130
+ }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
30131
+ packageName: string().min(1),
30132
+ nodeId: string().optional(),
30133
+ everywhere: boolean().optional()
30134
+ }), UninstallPackageResultSchema, {
29967
30135
  kind: "mutation",
29968
30136
  auth: "admin"
29969
- }), method(_void(), ReloadPackagesResultSchema, {
30137
+ }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
29970
30138
  kind: "mutation",
29971
30139
  auth: "admin"
29972
30140
  }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
@@ -39884,6 +40052,32 @@ var TotpStatusSchema = object({
39884
40052
  /** Null when no row exists OR the row is still pending confirmation. */
39885
40053
  confirmedAt: number().nullable()
39886
40054
  });
40055
+ /**
40056
+ * user-management — singleton capability for user accounts, API keys,
40057
+ * and scoped tokens.
40058
+ *
40059
+ * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
40060
+ * — the subset check on `setUserScopes` / `createScopedToken` is moot
40061
+ * because non-admins never reach these. If/when we open non-admin
40062
+ * delegation, structural caller-scope subset check goes inside the
40063
+ * provider.
40064
+ */
40065
+ var ExternalIdentitySchema = object({
40066
+ /** Login-method id of the provider instance, e.g. `auth-oidc/authentik`. */
40067
+ provider: string(),
40068
+ /** The IdP's stable subject (`sub`) for this account. */
40069
+ subject: string(),
40070
+ /** The verified `iss` of the IdP the identity was linked under — `sub` is unique only per issuer. */
40071
+ issuer: string(),
40072
+ userId: string(),
40073
+ /** What the IdP called the account at link time (username / email) — display only. */
40074
+ label: string().optional(),
40075
+ linkedAt: number()
40076
+ });
40077
+ var ExternalIdentityKeySchema = object({
40078
+ provider: string().min(1),
40079
+ subject: string().min(1)
40080
+ });
39887
40081
  method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
39888
40082
  kind: "mutation",
39889
40083
  auth: "admin",
@@ -39997,7 +40191,22 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
39997
40191
  userId: string(),
39998
40192
  username: string(),
39999
40193
  scopes: array(TokenScopeSchema)
40000
- }).nullable(), { access: "view" }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40194
+ }).nullable(), { access: "view" }), method(object({ userId: string() }), array(ExternalIdentitySchema), { auth: "admin" }), method(ExternalIdentityKeySchema, object({
40195
+ userId: string(),
40196
+ issuer: string()
40197
+ }).nullable(), { auth: "admin" }), method(ExternalIdentityKeySchema.extend({
40198
+ userId: string(),
40199
+ issuer: string().min(1),
40200
+ label: string().optional()
40201
+ }), object({ success: literal(true) }), {
40202
+ kind: "mutation",
40203
+ auth: "admin",
40204
+ access: "create"
40205
+ }), method(ExternalIdentityKeySchema.extend({ userId: string() }), object({ success: boolean() }), {
40206
+ kind: "mutation",
40207
+ auth: "admin",
40208
+ access: "delete"
40209
+ }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40001
40210
  kind: "mutation",
40002
40211
  auth: "admin",
40003
40212
  access: "delete"
@@ -42407,6 +42616,12 @@ Object.freeze({
42407
42616
  addonId: null,
42408
42617
  access: "view"
42409
42618
  },
42619
+ "addons.listInstallations": {
42620
+ capName: "addons",
42621
+ capScope: "system",
42622
+ addonId: null,
42623
+ access: "view"
42624
+ },
42410
42625
  "addons.listJobs": {
42411
42626
  capName: "addons",
42412
42627
  capScope: "system",
@@ -46631,6 +46846,12 @@ Object.freeze({
46631
46846
  addonId: null,
46632
46847
  access: "create"
46633
46848
  },
46849
+ "pipelineAnalytics.setRetrainFrameComplete": {
46850
+ capName: "pipeline-analytics",
46851
+ capScope: "device",
46852
+ addonId: null,
46853
+ access: "create"
46854
+ },
46634
46855
  "pipelineAnalytics.setTrackFlags": {
46635
46856
  capName: "pipeline-analytics",
46636
46857
  capScope: "device",
@@ -46667,6 +46888,12 @@ Object.freeze({
46667
46888
  addonId: null,
46668
46889
  access: "delete"
46669
46890
  },
46891
+ "pipelineAnalytics.writeRetrainArchive": {
46892
+ capName: "pipeline-analytics",
46893
+ capScope: "device",
46894
+ addonId: null,
46895
+ access: "create"
46896
+ },
46670
46897
  "pipelineExecutor.cacheFrameInPool": {
46671
46898
  capName: "pipeline-executor",
46672
46899
  capScope: "system",
@@ -49019,18 +49246,36 @@ Object.freeze({
49019
49246
  addonId: null,
49020
49247
  access: "delete"
49021
49248
  },
49249
+ "userManagement.findUserByExternalIdentity": {
49250
+ capName: "user-management",
49251
+ capScope: "system",
49252
+ addonId: null,
49253
+ access: "view"
49254
+ },
49022
49255
  "userManagement.getTotpStatus": {
49023
49256
  capName: "user-management",
49024
49257
  capScope: "system",
49025
49258
  addonId: null,
49026
49259
  access: "view"
49027
49260
  },
49261
+ "userManagement.linkExternalIdentity": {
49262
+ capName: "user-management",
49263
+ capScope: "system",
49264
+ addonId: null,
49265
+ access: "create"
49266
+ },
49028
49267
  "userManagement.listApiKeys": {
49029
49268
  capName: "user-management",
49030
49269
  capScope: "system",
49031
49270
  addonId: null,
49032
49271
  access: "view"
49033
49272
  },
49273
+ "userManagement.listExternalIdentities": {
49274
+ capName: "user-management",
49275
+ capScope: "system",
49276
+ addonId: null,
49277
+ access: "view"
49278
+ },
49034
49279
  "userManagement.listOauthSessions": {
49035
49280
  capName: "user-management",
49036
49281
  capScope: "system",
@@ -49109,6 +49354,12 @@ Object.freeze({
49109
49354
  addonId: null,
49110
49355
  access: "create"
49111
49356
  },
49357
+ "userManagement.unlinkExternalIdentity": {
49358
+ capName: "user-management",
49359
+ capScope: "system",
49360
+ addonId: null,
49361
+ access: "delete"
49362
+ },
49112
49363
  "userManagement.updateUser": {
49113
49364
  capName: "user-management",
49114
49365
  capScope: "system",
@@ -52448,6 +52699,11 @@ Object.freeze({
52448
52699
  form: "single",
52449
52700
  optional: false
52450
52701
  }],
52702
+ "pipelineAnalytics.setRetrainFrameComplete": [{
52703
+ name: "deviceId",
52704
+ form: "single",
52705
+ optional: false
52706
+ }],
52451
52707
  "pipelineAnalytics.setTrackFlags": [{
52452
52708
  name: "deviceId",
52453
52709
  form: "single",
@@ -54535,7 +54791,7 @@ var PetkitRegionSchema = _enum(PETKIT_REGIONS);
54535
54791
  */
54536
54792
  var petkitConfigSchema = object({
54537
54793
  email: string().min(1).describe("PetKit account email"),
54538
- password: string().min(1).describe("PetKit account password"),
54794
+ password: string().min(1).describe("PetKit account password").meta({ secret: true }),
54539
54795
  region: PetkitRegionSchema.default("de").describe("PetKit cloud region"),
54540
54796
  timezone: string().default("Europe/Berlin").describe("IANA timezone used for cloud request headers"),
54541
54797
  pollIntervalMs: preprocess((v) => v === "" || v === null ? void 0 : v, number().int().min(0).max(36e5).default(3e4)).describe("Per-feeder poll cadence (ms) — 0 leaves only eager/stale refresh")
package/dist/addon.mjs CHANGED
@@ -6471,7 +6471,7 @@ var ZodIssueCode = {
6471
6471
  var ZodFirstPartyTypeKind;
6472
6472
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6473
6473
  //#endregion
6474
- //#region ../types/dist/sleep-BNeXenvr.mjs
6474
+ //#region ../types/dist/sleep-B0JG7-_F.mjs
6475
6475
  /**
6476
6476
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6477
6477
  * window to float samples (D455).
@@ -16197,6 +16197,10 @@ var DeviceInfoSchema = object({
16197
16197
  isCamera: boolean(),
16198
16198
  /** Current config values — serializable snapshot */
16199
16199
  config: record(string(), unknown()),
16200
+ /** Paths inside `config` the device's schema declares secret (D783) —
16201
+ * what the non-admin redaction withholds. Paths, never values. Absent
16202
+ * when the owning runner has not reported them. */
16203
+ secretConfigPaths: array(string()).optional(),
16200
16204
  /** Hardware + identity blob (manufacturer / model / firmware / sn /
16201
16205
  * uid / mac / …). Populated by drivers; editable via setMetadata. */
16202
16206
  metadata: record(string(), unknown()).nullable().optional(),
@@ -16402,7 +16406,13 @@ var DeviceRegisterPayloadSchema = object({
16402
16406
  * call (workers re-register on init), so probe-driven updates
16403
16407
  * (e.g. PTZ flag flipping after the abilities probe) propagate. */
16404
16408
  features: array(string()).optional(),
16405
- config: record(string(), unknown())
16409
+ config: record(string(), unknown()),
16410
+ /** Config paths the device's own schema DECLARES secret
16411
+ * (`.meta({ secret: true })` — dotted, `[]` for array items, e.g.
16412
+ * `connection.password`). Re-published on every register; the non-admin
16413
+ * redaction withholds them at any depth (D783). Optional: an older runner
16414
+ * omits it and the keyword backstop applies. */
16415
+ secretConfigPaths: array(string()).optional()
16406
16416
  });
16407
16417
  var DeviceRemovePayloadSchema = object({ deviceId: number() });
16408
16418
  var DevicePersistConfigPayloadSchema = object({
@@ -18061,7 +18071,14 @@ var LoginMethodContributionSchema = discriminatedUnion("kind", [
18061
18071
  icon: string().optional(),
18062
18072
  /** Addon-owned HTTP route the button navigates to (GET). */
18063
18073
  startUrl: string(),
18064
- stage: LoginStageEnum
18074
+ stage: LoginStageEnum,
18075
+ /**
18076
+ * The provider names an external identity a signed-in user can link to
18077
+ * their own account (D782): `auth.listLinkableProviders` /
18078
+ * `beginExternalLink` offer exactly the redirect methods that set this,
18079
+ * whatever their id. Absent / false — a login button only (magic-link).
18080
+ */
18081
+ linkable: boolean().optional()
18065
18082
  }),
18066
18083
  object({
18067
18084
  kind: literal("widget"),
@@ -23496,7 +23513,13 @@ var RetrainFrameSchema = object({
23496
23513
  sizeBytes: number().int(),
23497
23514
  width: number().int(),
23498
23515
  height: number().int(),
23499
- copiedAt: number()
23516
+ copiedAt: number(),
23517
+ /** When the CAMERA captured the frame. Absent on a copy taken before D785. */
23518
+ capturedAt: number().optional(),
23519
+ /** The operator's "every subject in this frame is boxed". Detector
23520
+ * evaluation keeps only complete frames: an unboxed subject would count as
23521
+ * a false positive. */
23522
+ complete: boolean()
23500
23523
  });
23501
23524
  /** Why a copy-on-select could not be honoured — named, never a silent skip. */
23502
23525
  var RetrainCopyRefusalSchema = _enum([
@@ -23517,6 +23540,51 @@ var RetrainFrameListSchema = object({
23517
23540
  /** What the page pre-selects — the native key frame when one survives. */
23518
23541
  autoPickMediaId: number().int().optional()
23519
23542
  });
23543
+ /**
23544
+ * Which frames an annotated export carries. Every field narrows; an empty
23545
+ * filter is every annotated copy. A dataset VERSION is a frozen `frameIds`
23546
+ * list owned by whoever trains (the training orchestrator), so `frameIds` is
23547
+ * the primitive a version export uses; `batchId` re-selects what an earlier
23548
+ * export carried (`exportedInBatch`).
23549
+ */
23550
+ var RetrainExportFilterSchema = object({
23551
+ deviceIds: array(number()).optional(),
23552
+ frameIds: array(string()).max(2e4).optional(),
23553
+ batchId: string().optional(),
23554
+ /** Only frames the operator marked complete (all subjects boxed). */
23555
+ completeOnly: boolean().optional()
23556
+ });
23557
+ /**
23558
+ * `frames`: the full frame copies, boxes in `annotations.json`.
23559
+ * `crops`: additionally one JPEG per subject, cut with the runtime detail-crop
23560
+ * convention — the classifier layout.
23561
+ */
23562
+ var RetrainExportLayoutSchema = _enum(["frames", "crops"]);
23563
+ /**
23564
+ * Where `writeRetrainArchive` streams the tar: one HTTP request whose body is
23565
+ * the archive, sent chunk by chunk. Covers a presigned PUT and a provider
23566
+ * addon's data-plane upload route alike. Headers are sent verbatim and never
23567
+ * logged.
23568
+ */
23569
+ var RetrainArchiveTargetSchema = object({
23570
+ kind: literal("http"),
23571
+ method: _enum(["PUT", "POST"]),
23572
+ url: string().url(),
23573
+ headers: record(string(), string()).optional()
23574
+ });
23575
+ var RetrainArchiveResultSchema = object({
23576
+ batchId: string(),
23577
+ frames: number().int(),
23578
+ crops: number().int(),
23579
+ annotations: number().int(),
23580
+ /** Frames planned but not shipped (unreadable copy, path too long). */
23581
+ missing: number().int(),
23582
+ bytes: number().int(),
23583
+ /** sha256 of the exact bytes sent. */
23584
+ sha256: string(),
23585
+ /** The target's HTTP status. */
23586
+ status: number().int()
23587
+ });
23520
23588
  /** What the operator asked the assist to look for. */
23521
23589
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
23522
23590
  kind: literal("package"),
@@ -24311,9 +24379,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
24311
24379
  }), RetrainTransitionResultSchema, {
24312
24380
  kind: "mutation",
24313
24381
  auth: "admin"
24314
- }), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
24382
+ }), method(RetrainExportFilterSchema.extend({ layout: RetrainExportLayoutSchema.optional() }), object({ url: string() }), {
24315
24383
  kind: "query",
24316
24384
  auth: "admin"
24385
+ }), method(object({
24386
+ deviceId: number(),
24387
+ trackId: string(),
24388
+ frameId: string(),
24389
+ complete: boolean()
24390
+ }), RetrainFrameSchema, {
24391
+ kind: "mutation",
24392
+ auth: "admin"
24393
+ }), method(object({
24394
+ filter: RetrainExportFilterSchema,
24395
+ layout: RetrainExportLayoutSchema,
24396
+ target: RetrainArchiveTargetSchema
24397
+ }), RetrainArchiveResultSchema, {
24398
+ kind: "mutation",
24399
+ auth: "admin",
24400
+ timeoutMs: 60 * 6e4
24317
24401
  }), method(object({
24318
24402
  /** Which of the three event tables owns the row. */
24319
24403
  ownerType: EventOwnerTypeSchema,
@@ -27643,7 +27727,19 @@ var SsoBridgeClaimsSchema = object({
27643
27727
  * editing a descriptor must not retroactively extend or shorten a link the
27644
27728
  * operator already consented to.
27645
27729
  */
27646
- refreshTtl: union([number().int().positive(), literal("never")]).optional()
27730
+ refreshTtl: union([number().int().positive(), literal("never")]).optional(),
27731
+ /**
27732
+ * Opaque handle of a hub-side LINK intent (D782). Set by an OIDC callback
27733
+ * that was started from a signed-in user's "Link" button: the finish then
27734
+ * links this identity to the intent's user instead of signing anyone in.
27735
+ * The handle carries no user id — the hub resolves it, single-use.
27736
+ */
27737
+ linkIntent: string().optional(),
27738
+ /**
27739
+ * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
27740
+ * subject is unique only per issuer, so a link is bound to it.
27741
+ */
27742
+ issuer: string().optional()
27647
27743
  });
27648
27744
  method(object({
27649
27745
  claims: SsoBridgeClaimsSchema,
@@ -29578,7 +29674,22 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
29578
29674
  * field their hints were silently stripped by the schema and the
29579
29675
  * adaptive ladder started blind on the client's display size.
29580
29676
  */
29581
- hints: webrtcClientHintsSchema.optional()
29677
+ hints: webrtcClientHintsSchema.optional(),
29678
+ /**
29679
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
29680
+ * through the `intercom` cap's push-talk triple. When `true` and the
29681
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
29682
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
29683
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
29684
+ *
29685
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
29686
+ * with `intercom`, when the linked user may control that camera. The
29687
+ * hub STRIPS it from every request-bound call (a browser), exactly as
29688
+ * it overwrites `relayOnly` — a viewer's talk permission is the
29689
+ * intercom cap's own surface (share tokens gate it there), and this
29690
+ * flag must not become a second door to the camera's speaker.
29691
+ */
29692
+ talkback: boolean().optional()
29582
29693
  }), object({
29583
29694
  sessionId: string(),
29584
29695
  sdpAnswer: string()
@@ -29880,6 +29991,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
29880
29991
  var RestartAddonResultSchema = unknown();
29881
29992
  var InstallPackageResultSchema = unknown();
29882
29993
  var ReloadPackagesResultSchema = unknown();
29994
+ /**
29995
+ * What an uninstall did on ONE node.
29996
+ * - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
29997
+ * - `not-installed` — the node did not have it (nothing to do).
29998
+ * - `refused` — protected / bootstrap package; nothing touched.
29999
+ * - `failed` — attempted and did not complete; `error` says why.
30000
+ * - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
30001
+ * back-fill never returns the package, and the stale-addon sweep removes the
30002
+ * copy when the node registers again (only once the hub no longer has it).
30003
+ */
30004
+ var UninstallNodeOutcomeSchema = _enum([
30005
+ "uninstalled",
30006
+ "not-installed",
30007
+ "refused",
30008
+ "failed",
30009
+ "pending-reconnect"
30010
+ ]);
30011
+ var UninstallNodeResultSchema = object({
30012
+ nodeId: string(),
30013
+ outcome: UninstallNodeOutcomeSchema,
30014
+ error: string().optional(),
30015
+ addonIds: array(string()).readonly(),
30016
+ runnersStopped: array(string()).readonly(),
30017
+ warnings: array(string()).readonly()
30018
+ });
30019
+ var UninstallPackageResultSchema = object({
30020
+ /** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
30021
+ success: boolean(),
30022
+ packageName: string(),
30023
+ results: array(UninstallNodeResultSchema).readonly()
30024
+ });
30025
+ /**
30026
+ * `unreachable` lists online agents whose status read FAILED — absence from
30027
+ * `installations` is only "not installed" for a node that answered (D315).
30028
+ */
30029
+ var PackageInstallationsSchema = object({
30030
+ installations: array(object({
30031
+ packageName: string(),
30032
+ nodeId: string(),
30033
+ nodeName: string(),
30034
+ isHub: boolean(),
30035
+ isOnline: boolean(),
30036
+ version: string().nullable(),
30037
+ addonIds: array(string()).readonly(),
30038
+ source: _enum(["live", "recorded"]),
30039
+ /** The hub installs this package too. `false` on an agent row = an orphan. */
30040
+ onHub: boolean()
30041
+ })).readonly(),
30042
+ unreachable: array(object({
30043
+ nodeId: string(),
30044
+ error: string()
30045
+ })).readonly()
30046
+ });
29883
30047
  var BulkUpdateItemStatusSchema = _enum([
29884
30048
  "queued",
29885
30049
  "updating",
@@ -29962,10 +30126,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
29962
30126
  }), method(object({ packageName: string() }), InstallPackageResultSchema, {
29963
30127
  kind: "mutation",
29964
30128
  auth: "admin"
29965
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({ packageName: string() }), unknown(), {
30129
+ }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
30130
+ packageName: string().min(1),
30131
+ nodeId: string().optional(),
30132
+ everywhere: boolean().optional()
30133
+ }), UninstallPackageResultSchema, {
29966
30134
  kind: "mutation",
29967
30135
  auth: "admin"
29968
- }), method(_void(), ReloadPackagesResultSchema, {
30136
+ }), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
29969
30137
  kind: "mutation",
29970
30138
  auth: "admin"
29971
30139
  }), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
@@ -39883,6 +40051,32 @@ var TotpStatusSchema = object({
39883
40051
  /** Null when no row exists OR the row is still pending confirmation. */
39884
40052
  confirmedAt: number().nullable()
39885
40053
  });
40054
+ /**
40055
+ * user-management — singleton capability for user accounts, API keys,
40056
+ * and scoped tokens.
40057
+ *
40058
+ * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
40059
+ * — the subset check on `setUserScopes` / `createScopedToken` is moot
40060
+ * because non-admins never reach these. If/when we open non-admin
40061
+ * delegation, structural caller-scope subset check goes inside the
40062
+ * provider.
40063
+ */
40064
+ var ExternalIdentitySchema = object({
40065
+ /** Login-method id of the provider instance, e.g. `auth-oidc/authentik`. */
40066
+ provider: string(),
40067
+ /** The IdP's stable subject (`sub`) for this account. */
40068
+ subject: string(),
40069
+ /** The verified `iss` of the IdP the identity was linked under — `sub` is unique only per issuer. */
40070
+ issuer: string(),
40071
+ userId: string(),
40072
+ /** What the IdP called the account at link time (username / email) — display only. */
40073
+ label: string().optional(),
40074
+ linkedAt: number()
40075
+ });
40076
+ var ExternalIdentityKeySchema = object({
40077
+ provider: string().min(1),
40078
+ subject: string().min(1)
40079
+ });
39886
40080
  method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
39887
40081
  kind: "mutation",
39888
40082
  auth: "admin",
@@ -39996,7 +40190,22 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
39996
40190
  userId: string(),
39997
40191
  username: string(),
39998
40192
  scopes: array(TokenScopeSchema)
39999
- }).nullable(), { access: "view" }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40193
+ }).nullable(), { access: "view" }), method(object({ userId: string() }), array(ExternalIdentitySchema), { auth: "admin" }), method(ExternalIdentityKeySchema, object({
40194
+ userId: string(),
40195
+ issuer: string()
40196
+ }).nullable(), { auth: "admin" }), method(ExternalIdentityKeySchema.extend({
40197
+ userId: string(),
40198
+ issuer: string().min(1),
40199
+ label: string().optional()
40200
+ }), object({ success: literal(true) }), {
40201
+ kind: "mutation",
40202
+ auth: "admin",
40203
+ access: "create"
40204
+ }), method(ExternalIdentityKeySchema.extend({ userId: string() }), object({ success: boolean() }), {
40205
+ kind: "mutation",
40206
+ auth: "admin",
40207
+ access: "delete"
40208
+ }), method(_void(), array(OauthSessionSummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: boolean() }), {
40000
40209
  kind: "mutation",
40001
40210
  auth: "admin",
40002
40211
  access: "delete"
@@ -42406,6 +42615,12 @@ Object.freeze({
42406
42615
  addonId: null,
42407
42616
  access: "view"
42408
42617
  },
42618
+ "addons.listInstallations": {
42619
+ capName: "addons",
42620
+ capScope: "system",
42621
+ addonId: null,
42622
+ access: "view"
42623
+ },
42409
42624
  "addons.listJobs": {
42410
42625
  capName: "addons",
42411
42626
  capScope: "system",
@@ -46630,6 +46845,12 @@ Object.freeze({
46630
46845
  addonId: null,
46631
46846
  access: "create"
46632
46847
  },
46848
+ "pipelineAnalytics.setRetrainFrameComplete": {
46849
+ capName: "pipeline-analytics",
46850
+ capScope: "device",
46851
+ addonId: null,
46852
+ access: "create"
46853
+ },
46633
46854
  "pipelineAnalytics.setTrackFlags": {
46634
46855
  capName: "pipeline-analytics",
46635
46856
  capScope: "device",
@@ -46666,6 +46887,12 @@ Object.freeze({
46666
46887
  addonId: null,
46667
46888
  access: "delete"
46668
46889
  },
46890
+ "pipelineAnalytics.writeRetrainArchive": {
46891
+ capName: "pipeline-analytics",
46892
+ capScope: "device",
46893
+ addonId: null,
46894
+ access: "create"
46895
+ },
46669
46896
  "pipelineExecutor.cacheFrameInPool": {
46670
46897
  capName: "pipeline-executor",
46671
46898
  capScope: "system",
@@ -49018,18 +49245,36 @@ Object.freeze({
49018
49245
  addonId: null,
49019
49246
  access: "delete"
49020
49247
  },
49248
+ "userManagement.findUserByExternalIdentity": {
49249
+ capName: "user-management",
49250
+ capScope: "system",
49251
+ addonId: null,
49252
+ access: "view"
49253
+ },
49021
49254
  "userManagement.getTotpStatus": {
49022
49255
  capName: "user-management",
49023
49256
  capScope: "system",
49024
49257
  addonId: null,
49025
49258
  access: "view"
49026
49259
  },
49260
+ "userManagement.linkExternalIdentity": {
49261
+ capName: "user-management",
49262
+ capScope: "system",
49263
+ addonId: null,
49264
+ access: "create"
49265
+ },
49027
49266
  "userManagement.listApiKeys": {
49028
49267
  capName: "user-management",
49029
49268
  capScope: "system",
49030
49269
  addonId: null,
49031
49270
  access: "view"
49032
49271
  },
49272
+ "userManagement.listExternalIdentities": {
49273
+ capName: "user-management",
49274
+ capScope: "system",
49275
+ addonId: null,
49276
+ access: "view"
49277
+ },
49033
49278
  "userManagement.listOauthSessions": {
49034
49279
  capName: "user-management",
49035
49280
  capScope: "system",
@@ -49108,6 +49353,12 @@ Object.freeze({
49108
49353
  addonId: null,
49109
49354
  access: "create"
49110
49355
  },
49356
+ "userManagement.unlinkExternalIdentity": {
49357
+ capName: "user-management",
49358
+ capScope: "system",
49359
+ addonId: null,
49360
+ access: "delete"
49361
+ },
49111
49362
  "userManagement.updateUser": {
49112
49363
  capName: "user-management",
49113
49364
  capScope: "system",
@@ -52447,6 +52698,11 @@ Object.freeze({
52447
52698
  form: "single",
52448
52699
  optional: false
52449
52700
  }],
52701
+ "pipelineAnalytics.setRetrainFrameComplete": [{
52702
+ name: "deviceId",
52703
+ form: "single",
52704
+ optional: false
52705
+ }],
52450
52706
  "pipelineAnalytics.setTrackFlags": [{
52451
52707
  name: "deviceId",
52452
52708
  form: "single",
@@ -54534,7 +54790,7 @@ var PetkitRegionSchema = _enum(PETKIT_REGIONS);
54534
54790
  */
54535
54791
  var petkitConfigSchema = object({
54536
54792
  email: string().min(1).describe("PetKit account email"),
54537
- password: string().min(1).describe("PetKit account password"),
54793
+ password: string().min(1).describe("PetKit account password").meta({ secret: true }),
54538
54794
  region: PetkitRegionSchema.default("de").describe("PetKit cloud region"),
54539
54795
  timezone: string().default("Europe/Berlin").describe("IANA timezone used for cloud request headers"),
54540
54796
  pollIntervalMs: preprocess((v) => v === "" || v === null ? void 0 : v, number().int().min(0).max(36e5).default(3e4)).describe("Per-feeder poll cadence (ms) — 0 leaves only eager/stale refresh")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.2.120",
3
+ "version": "0.2.122",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",