@camstack/core 0.1.37 → 0.1.39

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 (82) hide show
  1. package/dist/auth/auth-manager.d.ts +12 -1
  2. package/dist/auth/auth-manager.d.ts.map +1 -1
  3. package/dist/auth/scope-matcher.d.ts +8 -0
  4. package/dist/auth/scope-matcher.d.ts.map +1 -0
  5. package/dist/auth/totp-manager.d.ts +0 -1
  6. package/dist/auth/totp-manager.d.ts.map +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +15 -0
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts.map +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +27 -6
  10. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js.map +1 -1
  11. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +27 -6
  12. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -1
  13. package/dist/builtins/device-manager/device-config-contribution.d.ts +33 -0
  14. package/dist/builtins/device-manager/device-config-contribution.d.ts.map +1 -0
  15. package/dist/builtins/device-manager/device-manager.addon.d.ts +52 -17
  16. package/dist/builtins/device-manager/device-manager.addon.d.ts.map +1 -1
  17. package/dist/builtins/device-manager/device-manager.addon.js +285 -161
  18. package/dist/builtins/device-manager/device-manager.addon.js.map +1 -1
  19. package/dist/builtins/device-manager/device-manager.addon.mjs +286 -162
  20. package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -1
  21. package/dist/builtins/local-auth/auth-schema.d.ts +1 -0
  22. package/dist/builtins/local-auth/auth-schema.d.ts.map +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.d.ts +1 -0
  24. package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -1
  25. package/dist/builtins/local-auth/local-auth.addon.js +354 -3
  26. package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
  27. package/dist/builtins/local-auth/local-auth.addon.mjs +355 -3
  28. package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
  29. package/dist/builtins/local-auth/oauth-grants.d.ts +46 -0
  30. package/dist/builtins/local-auth/oauth-grants.d.ts.map +1 -0
  31. package/dist/builtins/local-auth/oauth-session-manager.d.ts +51 -0
  32. package/dist/builtins/local-auth/oauth-session-manager.d.ts.map +1 -0
  33. package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +97 -0
  34. package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts.map +1 -0
  35. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +24 -1
  36. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts.map +1 -1
  37. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +136 -56
  38. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js.map +1 -1
  39. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +137 -57
  40. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs.map +1 -1
  41. package/dist/builtins/snapshot/index.js +1 -3
  42. package/dist/builtins/snapshot/index.js.map +1 -1
  43. package/dist/builtins/snapshot/index.mjs +1 -3
  44. package/dist/builtins/snapshot/index.mjs.map +1 -1
  45. package/dist/builtins/snapshot/snapshot.addon.d.ts.map +1 -1
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +428 -234
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.mjs +428 -235
  51. package/dist/index.mjs.map +1 -1
  52. package/package.json +19 -37
  53. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts +0 -8
  54. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +0 -1
  55. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +0 -75
  56. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +0 -1
  57. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +0 -69
  58. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +0 -1
  59. package/dist/builtins/auth-orchestrator/index.d.ts +0 -2
  60. package/dist/builtins/auth-orchestrator/index.d.ts.map +0 -1
  61. package/dist/builtins/auth-orchestrator/index.js +0 -7
  62. package/dist/builtins/auth-orchestrator/index.mjs +0 -2
  63. package/dist/builtins/mesh-orchestrator/index.d.ts +0 -2
  64. package/dist/builtins/mesh-orchestrator/index.d.ts.map +0 -1
  65. package/dist/builtins/mesh-orchestrator/index.js +0 -7
  66. package/dist/builtins/mesh-orchestrator/index.mjs +0 -2
  67. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts +0 -9
  68. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts.map +0 -1
  69. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js +0 -113
  70. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js.map +0 -1
  71. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs +0 -107
  72. package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs.map +0 -1
  73. package/dist/builtins/turn-orchestrator/index.d.ts +0 -2
  74. package/dist/builtins/turn-orchestrator/index.d.ts.map +0 -1
  75. package/dist/builtins/turn-orchestrator/index.js +0 -7
  76. package/dist/builtins/turn-orchestrator/index.mjs +0 -2
  77. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts +0 -34
  78. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts.map +0 -1
  79. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js +0 -126
  80. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js.map +0 -1
  81. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs +0 -120
  82. package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -31,7 +31,7 @@ import { promisify } from "node:util";
31
31
  import { errMsg, parseJsonObject } from "@camstack/types";
32
32
  import * as vm from "node:vm";
33
33
  import * as os from "node:os";
34
- //#region ../types/dist/index-Ce7RZWP4.mjs
34
+ //#region ../types/dist/index-CgPd35k5.mjs
35
35
  var MODEL_FORMATS = [
36
36
  "onnx",
37
37
  "coreml",
@@ -106,6 +106,12 @@ Object.fromEntries([
106
106
  icon: "video",
107
107
  order: 35
108
108
  },
109
+ {
110
+ id: "ptz",
111
+ label: "PTZ",
112
+ icon: "move",
113
+ order: 40
114
+ },
109
115
  {
110
116
  id: "pipeline",
111
117
  label: "Detection Pipeline",
@@ -232,7 +238,19 @@ var DecoderSessionConfigSchema = z.object({
232
238
  * on every line so `grep tag=broker:5/high` filters one camera
233
239
  * profile cleanly.
234
240
  */
235
- tag: z.string().optional()
241
+ tag: z.string().optional(),
242
+ /**
243
+ * Where the session delivers decoded frames (Phase 5 / D9):
244
+ *
245
+ * - `'callback'` (default) — the legacy pixel path: decoded frames are
246
+ * buffered as `DecodedFrame`s and drained via `pullFrames`.
247
+ * - `'shm'` — the shared-memory frame plane: decoded frames are written
248
+ * into an OS shared-memory ring and drained as zero-pixel
249
+ * `FrameHandle`s via `pullHandles`. A session is one mode or the
250
+ * other — `pullFrames` returns nothing for an `'shm'` session and
251
+ * `pullHandles` returns nothing for a `'callback'` session.
252
+ */
253
+ frameSink: z.enum(["callback", "shm"]).default("callback")
236
254
  });
237
255
  function errMsg$1(err) {
238
256
  if (err instanceof Error) return err.message;
@@ -892,6 +910,63 @@ var DecodedFrameSchema = z.object({
892
910
  ]),
893
911
  timestamp: z.number()
894
912
  });
913
+ var FrameHandleSchema = z.object({
914
+ shmId: z.string(),
915
+ slot: z.number().int().nonnegative(),
916
+ seq: z.number().int().nonnegative(),
917
+ width: z.number().int().positive(),
918
+ height: z.number().int().positive(),
919
+ format: z.enum([
920
+ "jpeg",
921
+ "rgb",
922
+ "bgr",
923
+ "yuv420",
924
+ "gray"
925
+ ]),
926
+ pts: z.number(),
927
+ byteLength: z.number().int().nonnegative(),
928
+ nodeId: z.string(),
929
+ slotCount: z.number().int().positive()
930
+ });
931
+ var FrameHandleFormatSchema = z.enum([
932
+ "rgb",
933
+ "bgr",
934
+ "yuv420",
935
+ "gray"
936
+ ]);
937
+ var SubscribeFramesInputSchema = z.object({
938
+ brokerId: z.string(),
939
+ format: FrameHandleFormatSchema,
940
+ /**
941
+ * Optional reader-side cadence hint in frames per second. The broker does
942
+ * NOT throttle — latest-wins ring reads drop frames implicitly for a slow
943
+ * consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
944
+ * the consumer can pace its own `pullFrameHandles` polling.
945
+ */
946
+ maxFps: z.number().positive().optional(),
947
+ /** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
948
+ tag: z.string().optional()
949
+ });
950
+ var SubscribeFramesResultSchema = z.object({
951
+ /** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
952
+ subscriptionId: z.string(),
953
+ /** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
954
+ maxFps: z.number().nonnegative()
955
+ });
956
+ var DecodedAudioChunkSchema = z.object({
957
+ data: z.instanceof(Uint8Array),
958
+ sampleRate: z.number().int().positive(),
959
+ channels: z.number().int().positive(),
960
+ timestamp: z.number()
961
+ });
962
+ var SubscribeAudioChunksInputSchema = z.object({
963
+ brokerId: z.string(),
964
+ /** Short caller-identity tag (`audio-analyzer`, …) for `listClients`. */
965
+ tag: z.string().optional()
966
+ });
967
+ var SubscribeAudioChunksResultSchema = z.object({
968
+ /** Opaque id passed to `pullAudioChunks` / `unsubscribeAudioChunks`. */
969
+ subscriptionId: z.string() });
895
970
  var BrokerStatusSchema$1 = z.enum([
896
971
  "idle",
897
972
  "connecting",
@@ -1094,7 +1169,13 @@ method(z.object({
1094
1169
  }), {
1095
1170
  kind: "mutation",
1096
1171
  auth: "admin"
1097
- }), method(z.object({ brokerId: z.string() }), z.custom()), method(z.object({
1172
+ }), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(z.object({
1173
+ subscriptionId: z.string(),
1174
+ maxCount: z.number().int().positive().default(8)
1175
+ }), z.array(DecodedAudioChunkSchema).readonly()), method(z.object({ subscriptionId: z.string() }), z.object({ released: z.boolean() }), { kind: "mutation" }), method(SubscribeFramesInputSchema, SubscribeFramesResultSchema, { kind: "mutation" }), method(z.object({
1176
+ subscriptionId: z.string(),
1177
+ maxCount: z.number().int().positive().default(4)
1178
+ }), z.array(FrameHandleSchema).readonly()), method(z.object({ subscriptionId: z.string() }), z.object({ released: z.boolean() }), { kind: "mutation" }), method(z.object({
1098
1179
  brokerId: z.string(),
1099
1180
  seconds: z.number().min(0).max(30)
1100
1181
  }), z.void(), {
@@ -1787,6 +1868,34 @@ DeviceType$1.Light, DeviceType$1.Siren, DeviceType$1.Switch, method(z.object({
1787
1868
  enabled: z.boolean(),
1788
1869
  lastChangedAt: z.number()
1789
1870
  });
1871
+ z.object({
1872
+ enabled: z.boolean(),
1873
+ sensitivity: z.number(),
1874
+ /** Row-major active-cell grid. Length = gridWidth*gridHeight (see getOptions). */
1875
+ cells: z.array(z.boolean()),
1876
+ lastFetchedAt: z.number()
1877
+ });
1878
+ var MotionZoneOptionsSchema = z.object({
1879
+ gridWidth: z.number(),
1880
+ gridHeight: z.number(),
1881
+ sensitivity: z.object({
1882
+ min: z.number(),
1883
+ max: z.number(),
1884
+ step: z.number()
1885
+ })
1886
+ });
1887
+ var MotionZonePatchSchema = z.object({
1888
+ enabled: z.boolean().optional(),
1889
+ sensitivity: z.number().optional(),
1890
+ cells: z.array(z.boolean()).optional()
1891
+ });
1892
+ DeviceType$1.Camera, method(z.object({ deviceId: z.number() }), MotionZoneOptionsSchema), method(z.object({
1893
+ deviceId: z.number(),
1894
+ patch: MotionZonePatchSchema
1895
+ }), z.void(), {
1896
+ kind: "mutation",
1897
+ auth: "admin"
1898
+ });
1790
1899
  var AutotrackTargetTypeSchema = z.string().describe("Vendor target string (people/vehicle/pet); empty = camera default");
1791
1900
  var PtzAutotrackSettingsSchema = z.object({
1792
1901
  targetType: AutotrackTargetTypeSchema,
@@ -1829,6 +1938,85 @@ DeviceType$1.Camera, method(z.object({ deviceId: z.number() }), PtzAutotrackStat
1829
1938
  deviceId: z.number(),
1830
1939
  status: PtzAutotrackStatusSchema
1831
1940
  });
1941
+ var StreamProfileSchema = z.enum([
1942
+ "main",
1943
+ "sub",
1944
+ "ext"
1945
+ ]);
1946
+ var StreamProfileConfigSchema = z.object({
1947
+ width: z.number(),
1948
+ height: z.number(),
1949
+ codec: z.enum(["h264", "h265"]),
1950
+ framerate: z.number(),
1951
+ bitrate: z.number(),
1952
+ bitrateMode: z.enum(["vbr", "cbr"]).optional(),
1953
+ encoderProfile: z.enum([
1954
+ "high",
1955
+ "main",
1956
+ "baseline"
1957
+ ]).optional(),
1958
+ gop: z.number().optional(),
1959
+ audio: z.boolean().optional()
1960
+ });
1961
+ z.object({
1962
+ /** Per-profile current config. A profile absent = the camera doesn't have it. */
1963
+ main: StreamProfileConfigSchema.optional(),
1964
+ sub: StreamProfileConfigSchema.optional(),
1965
+ ext: StreamProfileConfigSchema.optional(),
1966
+ lastFetchedAt: z.number()
1967
+ });
1968
+ var StreamProfileOptionsSchema = z.object({
1969
+ resolutions: z.array(z.object({
1970
+ width: z.number(),
1971
+ height: z.number()
1972
+ })),
1973
+ codecs: z.array(z.enum(["h264", "h265"])),
1974
+ framerates: z.array(z.number()),
1975
+ /** Allowed bitrate values (kbps). Empty if the camera takes a free range. */
1976
+ bitrates: z.array(z.number()),
1977
+ /** Optional [min,max] kbps when the camera accepts a continuous range. */
1978
+ bitrateRange: z.tuple([z.number(), z.number()]).optional(),
1979
+ supportsBitrateMode: z.boolean(),
1980
+ supportsEncoderProfile: z.boolean(),
1981
+ supportsGop: z.boolean(),
1982
+ /** Allowed GOP / keyframe-interval range, in seconds — drives the
1983
+ * I-frame-interval selector. Absent when the camera advertises GOP
1984
+ * support but no concrete range (callers then fall back to a free
1985
+ * numeric input). `{ min, max, step }` per the getOptions convention. */
1986
+ gop: z.object({
1987
+ min: z.number(),
1988
+ max: z.number(),
1989
+ step: z.number()
1990
+ }).optional()
1991
+ });
1992
+ var StreamParamsOptionsSchema = z.object({
1993
+ main: StreamProfileOptionsSchema.optional(),
1994
+ sub: StreamProfileOptionsSchema.optional(),
1995
+ ext: StreamProfileOptionsSchema.optional()
1996
+ });
1997
+ var StreamProfilePatchSchema = z.object({
1998
+ width: z.number().optional(),
1999
+ height: z.number().optional(),
2000
+ codec: z.enum(["h264", "h265"]).optional(),
2001
+ framerate: z.number().optional(),
2002
+ bitrate: z.number().optional(),
2003
+ bitrateMode: z.enum(["vbr", "cbr"]).optional(),
2004
+ encoderProfile: z.enum([
2005
+ "high",
2006
+ "main",
2007
+ "baseline"
2008
+ ]).optional(),
2009
+ gop: z.number().optional(),
2010
+ audio: z.boolean().optional()
2011
+ });
2012
+ DeviceType$1.Camera, method(z.object({ deviceId: z.number() }), StreamParamsOptionsSchema), method(z.object({
2013
+ deviceId: z.number(),
2014
+ profile: StreamProfileSchema,
2015
+ patch: StreamProfilePatchSchema
2016
+ }), z.void(), {
2017
+ kind: "mutation",
2018
+ auth: "admin"
2019
+ }), method(z.object({ deviceId: z.number() }), z.unknown().nullable());
1832
2020
  z.object({
1833
2021
  on: z.boolean(),
1834
2022
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
@@ -2468,6 +2656,85 @@ method(LogEntrySchema, z.void(), { kind: "mutation" }), method(z.object({
2468
2656
  var StaticDirOutputSchema = z.object({ staticDir: z.string() });
2469
2657
  var VersionOutputSchema = z.object({ version: z.string() });
2470
2658
  method(z.void(), StaticDirOutputSchema), method(z.void(), VersionOutputSchema);
2659
+ var MethodAccessSchema = z.enum([
2660
+ "view",
2661
+ "create",
2662
+ "delete"
2663
+ ]);
2664
+ var AllowedProviderSchema = z.union([z.literal("*"), z.array(z.string())]);
2665
+ var AllowedDevicesSchema = z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]));
2666
+ var CapScopeSchema = z.enum(["device", "system"]);
2667
+ var TokenScopeSchema = z.discriminatedUnion("type", [
2668
+ z.object({
2669
+ type: z.literal("category"),
2670
+ target: CapScopeSchema,
2671
+ access: z.array(MethodAccessSchema).min(1)
2672
+ }),
2673
+ z.object({
2674
+ type: z.literal("capability"),
2675
+ target: z.string(),
2676
+ access: z.array(MethodAccessSchema).min(1)
2677
+ }),
2678
+ z.object({
2679
+ type: z.literal("addon"),
2680
+ target: z.string(),
2681
+ access: z.array(MethodAccessSchema).min(1)
2682
+ }),
2683
+ z.object({
2684
+ type: z.literal("device"),
2685
+ /**
2686
+ * One or more deviceIds (serialised as strings for wire-format
2687
+ * consistency with the rest of the union). Matcher accepts if
2688
+ * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
2689
+ * of one scope-per-device when granting access to a set of cameras.
2690
+ */
2691
+ targets: z.array(z.string()).min(1),
2692
+ access: z.array(MethodAccessSchema).min(1)
2693
+ })
2694
+ ]);
2695
+ z.object({
2696
+ id: z.string(),
2697
+ username: z.string(),
2698
+ passwordHash: z.string(),
2699
+ /**
2700
+ * Admin bypass. When true, the middleware skips the scope-access
2701
+ * check entirely. There is no other axis of privilege; the legacy
2702
+ * role enum collapsed onto this boolean in v2.
2703
+ */
2704
+ isAdmin: z.boolean().default(false),
2705
+ allowedProviders: AllowedProviderSchema,
2706
+ allowedDevices: AllowedDevicesSchema,
2707
+ /**
2708
+ * Scopes granted to this user. Admins bypass; their `scopes` is
2709
+ * ignored. Non-admins without scopes are locked out of every
2710
+ * protected call.
2711
+ */
2712
+ scopes: z.array(TokenScopeSchema).default([]),
2713
+ createdAt: z.number(),
2714
+ updatedAt: z.number()
2715
+ });
2716
+ z.object({
2717
+ id: z.string(),
2718
+ label: z.string(),
2719
+ isAdmin: z.boolean().default(false),
2720
+ allowedProviders: AllowedProviderSchema,
2721
+ allowedDevices: AllowedDevicesSchema,
2722
+ tokenHash: z.string(),
2723
+ tokenPrefix: z.string(),
2724
+ createdAt: z.number(),
2725
+ lastUsedAt: z.number().optional()
2726
+ });
2727
+ z.object({
2728
+ id: z.string(),
2729
+ userId: z.string(),
2730
+ name: z.string(),
2731
+ tokenHash: z.string(),
2732
+ tokenPrefix: z.string(),
2733
+ scopes: z.array(TokenScopeSchema),
2734
+ expiresAt: z.number().nullish(),
2735
+ lastUsedAt: z.number().nullish(),
2736
+ createdAt: z.number()
2737
+ });
2471
2738
  var SsoBridgeClaimsSchema = z.object({
2472
2739
  userId: z.string(),
2473
2740
  username: z.string(),
@@ -2483,12 +2750,36 @@ var SsoBridgeClaimsSchema = z.object({
2483
2750
  * JWT WITHOUT verifying the signature — the hub re-verifies on every
2484
2751
  * inbound call so trust still rests with the signing hub.
2485
2752
  */
2486
- hubUrl: z.string().optional()
2753
+ hubUrl: z.string().optional(),
2754
+ /** Permission scopes baked into the token. Set by the OAuth
2755
+ * account-linking grant; absent on ordinary SSO-login tokens. */
2756
+ scopes: z.array(TokenScopeSchema).optional(),
2757
+ /** OAuth authorization-code binding — set only on `oauth-code` tokens. */
2758
+ redirectUri: z.string().optional(),
2759
+ integrationId: z.string().optional(),
2760
+ /** JWT ID — unique per issued code; consumed-set enforces single-use. */
2761
+ jti: z.string().optional(),
2762
+ /** OAuth session registry id — set on `oauth-access`/`oauth-refresh`
2763
+ * tokens so the verify path can check the session is not revoked. */
2764
+ sessionId: z.string().optional()
2487
2765
  });
2488
2766
  method(z.object({
2489
2767
  claims: SsoBridgeClaimsSchema,
2490
2768
  ttlSec: z.number().int().positive().optional()
2491
2769
  }), z.object({ token: z.string() })), method(z.object({ token: z.string() }), SsoBridgeClaimsSchema.nullable());
2770
+ var OauthIntegrationDescriptorSchema = z.object({
2771
+ /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
2772
+ integrationId: z.string(),
2773
+ /** Human label rendered on the consent page. */
2774
+ displayName: z.string(),
2775
+ /** Scopes baked into every token issued for this integration. */
2776
+ requestedScopes: z.array(TokenScopeSchema),
2777
+ /** Allowed redirect_uri prefixes. /api/oauth2/authorize rejects any
2778
+ * redirect_uri that does not start with one of these. Required —
2779
+ * an empty list means the integration can never complete linking. */
2780
+ allowedRedirectPrefixes: z.array(z.string()).min(1)
2781
+ });
2782
+ method(z.void(), OauthIntegrationDescriptorSchema);
2492
2783
  var PasskeySummarySchema = z.object({
2493
2784
  credentialId: z.string(),
2494
2785
  label: z.string(),
@@ -2734,22 +3025,29 @@ var WidgetSizeEnum = z.enum([
2734
3025
  "lg",
2735
3026
  "xl"
2736
3027
  ]);
3028
+ var WidgetRemoteSchema = z.object({
3029
+ remoteName: z.string(),
3030
+ exposedModule: z.string(),
3031
+ componentKey: z.string().optional()
3032
+ });
2737
3033
  var WidgetMetadataSchema = z.object({
2738
- /** Stable id within the addon kebab-case. */
2739
- stableId: z.string(),
3034
+ /** Primary host tab `'dashboard'`, `'device-tab'`, or a device-detail tab id. */
3035
+ tab: z.string(),
3036
+ /** Optional sub-tab within `tab`. */
3037
+ subTab: z.string().optional(),
2740
3038
  /** Operator-facing label. */
2741
3039
  label: z.string(),
3040
+ /** Ordering within `(tab, subTab)`, ascending. */
3041
+ order: z.number().optional(),
3042
+ /** Always `'remote'` — a widget is a Module Federation remote. */
3043
+ kind: z.literal("remote"),
3044
+ /** MF remote descriptor. */
3045
+ remote: WidgetRemoteSchema,
3046
+ /** Stable id within the addon — kebab-case. Equals `remote.componentKey`. */
3047
+ stableId: z.string(),
2742
3048
  description: z.string().optional(),
2743
3049
  icon: z.string().optional(),
2744
3050
  /**
2745
- * Module Federation remote name — must match the `name` field on the
2746
- * widget addon's `federation()` plugin config. Used by the host's
2747
- * `<WidgetRegistryProvider>` to call `loadRemote('<remoteName>/widgets')`.
2748
- * Conventionally `addon_<addonid>_widgets` (snake_case; MF names
2749
- * cannot contain hyphens).
2750
- */
2751
- remoteName: z.string(),
2752
- /**
2753
3051
  * Bundle filename inside the addon's `dist/` dir served at
2754
3052
  * `/api/addon-widgets/<addonId>/<bundle>`. With Module Federation
2755
3053
  * this is always `'remoteEntry.js'` — the value is kept on the
@@ -2757,9 +3055,9 @@ var WidgetMetadataSchema = z.object({
2757
3055
  * cache-buster URL without a separate filesystem stat.
2758
3056
  */
2759
3057
  bundle: z.string(),
2760
- /** Where the widget makes sense to render. */
3058
+ /** Every host the widget supports. The picker filters on this set. */
2761
3059
  hosts: z.array(WidgetHostEnum).readonly(),
2762
- /** Required props the host must supply. Validated at <WidgetSlot> mount. */
3060
+ /** Required props the host must supply. Validated at `<WidgetSlot>` mount. */
2763
3061
  requires: z.object({
2764
3062
  deviceContext: z.boolean().default(false),
2765
3063
  integrationContext: z.boolean().default(false)
@@ -2823,6 +3121,16 @@ var InvokeReplyEnvelopeSchema = z.object({
2823
3121
  contentType: z.string().optional()
2824
3122
  });
2825
3123
  method(z.void(), z.array(AddonHttpRouteSchema)), method(InvokeRequestSchema, InvokeReplyEnvelopeSchema, { kind: "mutation" });
3124
+ var ShmRingStatsSchema = z.object({
3125
+ sessionId: z.string(),
3126
+ slotCount: z.number().int(),
3127
+ slotByteLength: z.number().int(),
3128
+ segmentBytes: z.number().int(),
3129
+ budgetMb: z.number().int(),
3130
+ framesWritten: z.number().int(),
3131
+ getFrameHits: z.number().int(),
3132
+ getFrameMisses: z.number().int()
3133
+ });
2826
3134
  method(z.object({ codec: z.string() }), z.boolean()), method(z.void(), z.object({
2827
3135
  id: z.string(),
2828
3136
  name: z.string(),
@@ -2841,6 +3149,9 @@ method(z.object({ codec: z.string() }), z.boolean()), method(z.void(), z.object(
2841
3149
  sessionId: z.string(),
2842
3150
  maxCount: z.number().default(1)
2843
3151
  }), z.array(DecodedFrameSchema)), method(z.object({
3152
+ sessionId: z.string(),
3153
+ maxCount: z.number().default(1)
3154
+ }), z.array(FrameHandleSchema)), method(z.object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(z.object({ sessionId: z.string() }), ShmRingStatsSchema.nullable()), method(z.object({
2844
3155
  sessionId: z.string(),
2845
3156
  config: DecoderSessionConfigSchema.partial()
2846
3157
  }), z.void()), method(z.object({ sessionId: z.string() }), DecoderStatsSchema), method(z.void(), z.array(z.object({
@@ -3585,42 +3896,6 @@ method(z.object({
3585
3896
  username: z.string(),
3586
3897
  password: z.string()
3587
3898
  }), AuthResultSchema.nullable(), { kind: "mutation" }), method(z.object({ state: z.string() }), z.string()), method(z.record(z.string(), z.string()), AuthResultSchema, { kind: "mutation" }), method(z.object({ token: z.string() }), AuthResultSchema.nullable());
3588
- var AuthProviderInfoSchema = z.object({
3589
- /** Stable id matching the addon id (used for `getLoginUrl({addonId,…})`). */
3590
- addonId: z.string(),
3591
- /**
3592
- * Per-instance id when one addon registers multiple "logical"
3593
- * providers (e.g. OIDC with Google + Microsoft + custom). The login
3594
- * URL becomes `/addon/${addonId}/${instanceId}/start` — handler reads
3595
- * `:instanceId` from the route. Empty/unset means the addon is a
3596
- * single-instance provider; the URL is `/addon/${addonId}/start`.
3597
- */
3598
- instanceId: z.string().optional(),
3599
- /** Display label shown on the login button + admin row. */
3600
- displayName: z.string(),
3601
- /** Optional iconography hint (lucide-react icon name OR emoji). */
3602
- icon: z.string().optional(),
3603
- /** When true, the provider exposes a redirect-based login flow
3604
- * (`getLoginUrl` returns a URL the browser navigates to). */
3605
- hasRedirectFlow: z.boolean(),
3606
- /** When true, the provider exposes a credential-form login flow
3607
- * (`validateCredentials` accepts username + password). */
3608
- hasCredentialFlow: z.boolean(),
3609
- /** Provider kind, drives admin-UI hint dispatch (oidc / saml / totp / …). */
3610
- kind: z.string().optional(),
3611
- /** Operator-facing status string (e.g. "Connected to https://login.acme.com"). */
3612
- status: z.string().optional(),
3613
- /** When false, the provider is registered but disabled by config; the
3614
- * UI surfaces it as inactive without enumerating it for login. */
3615
- enabled: z.boolean()
3616
- });
3617
- method(z.void(), z.array(AuthProviderInfoSchema).readonly()), method(z.object({
3618
- addonId: z.string(),
3619
- enabled: z.boolean()
3620
- }), z.object({ success: z.literal(true) }), {
3621
- kind: "mutation",
3622
- auth: "admin"
3623
- });
3624
3899
  var NetworkEndpointSchema = z.object({
3625
3900
  url: z.string(),
3626
3901
  hostname: z.string(),
@@ -3646,33 +3921,6 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
3646
3921
  sourcePort: z.number().optional()
3647
3922
  });
3648
3923
  method(z.void(), NetworkEndpointSchema, { kind: "mutation" }), method(z.void(), z.void(), { kind: "mutation" }), method(z.void(), NetworkEndpointSchema.nullable()), method(z.void(), NetworkAccessStatusSchema), method(z.void(), z.array(NetworkEndpointEntrySchema).readonly());
3649
- var RemoteAccessEndpointSchema = z.object({
3650
- url: z.string(),
3651
- hostname: z.string(),
3652
- port: z.number(),
3653
- protocol: z.enum(["http", "https"])
3654
- });
3655
- var RemoteAccessProviderInfoSchema = z.object({
3656
- /** Stable id matching the addon id. */
3657
- addonId: z.string(),
3658
- /** Display label shown on the admin row — sourced from the addon manifest. */
3659
- displayName: z.string(),
3660
- /** When false, the provider is registered but disabled. */
3661
- enabled: z.boolean(),
3662
- /** True when the underlying tunnel/connection is up. */
3663
- connected: z.boolean(),
3664
- /** Public-facing endpoint, when connected. Null otherwise. */
3665
- endpoint: RemoteAccessEndpointSchema.nullable(),
3666
- /** Last error message (when connected=false), if available. */
3667
- error: z.string().optional()
3668
- });
3669
- method(z.void(), z.array(RemoteAccessProviderInfoSchema).readonly()), method(z.object({ addonId: z.string() }), RemoteAccessEndpointSchema, {
3670
- kind: "mutation",
3671
- auth: "admin"
3672
- }), method(z.object({ addonId: z.string() }), z.object({ success: z.literal(true) }), {
3673
- kind: "mutation",
3674
- auth: "admin"
3675
- });
3676
3924
  var TurnServerSchema = z.object({
3677
3925
  /** Single URL or list of URLs (e.g. "turn:turn.example.com:3478?transport=udp"). */
3678
3926
  urls: z.union([z.string(), z.array(z.string())]),
@@ -3680,33 +3928,6 @@ var TurnServerSchema = z.object({
3680
3928
  credential: z.string().optional()
3681
3929
  });
3682
3930
  method(z.void(), z.array(TurnServerSchema).readonly());
3683
- var TurnProviderInfoSchema = z.object({
3684
- /** Stable id matching the addon id. */
3685
- addonId: z.string(),
3686
- /** Display label shown on the admin row — sourced from the addon manifest. */
3687
- displayName: z.string(),
3688
- /** When false, the provider is registered but disabled. */
3689
- enabled: z.boolean(),
3690
- /** Number of servers this provider is currently exposing. */
3691
- serverCount: z.number(),
3692
- /**
3693
- * Flat list of every TURN/STUN URL this provider currently exposes.
3694
- * One row per URL (multi-URL ICE server entries are flattened). The
3695
- * admin UI shows this in a compact per-provider list so operators
3696
- * can verify what's actually being negotiated without having to dig
3697
- * into the combined `getAllServers` output.
3698
- */
3699
- urls: z.array(z.string()).readonly(),
3700
- /** Last fetch error (when serverCount=0 due to API failure), if any. */
3701
- error: z.string().optional()
3702
- });
3703
- method(z.void(), z.array(TurnProviderInfoSchema).readonly()), method(z.void(), z.array(TurnServerSchema).readonly()), method(z.object({
3704
- addonId: z.string(),
3705
- enabled: z.boolean()
3706
- }), z.object({ success: z.literal(true) }), {
3707
- kind: "mutation",
3708
- auth: "admin"
3709
- });
3710
3931
  var SnapshotImageSchema = z.object({
3711
3932
  base64: z.string(),
3712
3933
  contentType: z.string()
@@ -4309,10 +4530,38 @@ var PtzMoveCommandSchema = z.object({
4309
4530
  zoom: z.number().optional(),
4310
4531
  speed: z.number().optional()
4311
4532
  });
4533
+ PtzPositionSchema.extend({ autofocus: z.boolean() });
4534
+ var PtzOptionsSchema = z.object({
4535
+ hasPan: z.boolean(),
4536
+ hasTilt: z.boolean(),
4537
+ hasZoom: z.boolean(),
4538
+ supportsPresets: z.boolean(),
4539
+ /** Max number of named presets the camera supports, when known. */
4540
+ maxPresets: z.number().optional(),
4541
+ /** Whether the camera exposes a controllable autofocus toggle
4542
+ * (boolean `hasX` per the getOptions availability convention). */
4543
+ hasAutofocus: z.boolean()
4544
+ });
4312
4545
  DeviceType$1.Camera, method(PtzMoveCommandSchema.extend({ deviceId: z.number() }), z.void(), { kind: "mutation" }), method(PtzMoveCommandSchema.extend({ deviceId: z.number() }), z.void(), { kind: "mutation" }), method(z.object({ deviceId: z.number() }), z.void(), { kind: "mutation" }), method(z.object({ deviceId: z.number() }), z.array(PtzPresetSchema)), method(z.object({
4313
4546
  deviceId: z.number(),
4314
4547
  presetId: z.string()
4315
- }), z.void(), { kind: "mutation" }), method(z.object({ deviceId: z.number() }), z.void(), { kind: "mutation" }), method(z.object({ deviceId: z.number() }), PtzPositionSchema);
4548
+ }), z.void(), { kind: "mutation" }), method(z.object({
4549
+ deviceId: z.number(),
4550
+ presetId: z.string(),
4551
+ name: z.string()
4552
+ }), z.void(), {
4553
+ kind: "mutation",
4554
+ auth: "admin"
4555
+ }), method(z.object({
4556
+ deviceId: z.number(),
4557
+ presetId: z.string()
4558
+ }), z.void(), {
4559
+ kind: "mutation",
4560
+ auth: "admin"
4561
+ }), method(z.object({ deviceId: z.number() }), PtzOptionsSchema), method(z.object({ deviceId: z.number() }), z.void(), { kind: "mutation" }), method(z.object({ deviceId: z.number() }), PtzPositionSchema), method(z.object({
4562
+ deviceId: z.number(),
4563
+ enabled: z.boolean()
4564
+ }), z.void(), { kind: "mutation" });
4316
4565
  var EventItemSchema = z.object({
4317
4566
  id: z.string(),
4318
4567
  type: z.string(),
@@ -4803,7 +5052,7 @@ method(z.void(), ListResultSchema), method(z.void(), PreferredSchema), method(z.
4803
5052
  * tunnel always emits `https://` regardless. */
4804
5053
  scheme: z.enum(["http", "https"]).optional()
4805
5054
  }), GetConnectionEndpointsResultSchema), method(z.void(), AllowedAddressesSchema), method(AllowedAddressesSchema, z.object({ success: z.literal(true) }), { kind: "mutation" }), method(z.void(), AllowedAddressesSchema, { kind: "mutation" });
4806
- var MeshEndpointSchema$1 = z.object({
5055
+ var MeshEndpointSchema = z.object({
4807
5056
  /** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
4808
5057
  id: z.string(),
4809
5058
  /** Operator-facing label (e.g. "Mesh IPv4", "MagicDNS"). */
@@ -4880,7 +5129,7 @@ var MeshStatusSchema = z.object({
4880
5129
  /** Number of peers visible to this host (excluding self). */
4881
5130
  peerCount: z.number(),
4882
5131
  /** Every endpoint this provider exposes for the current host. */
4883
- endpoints: z.array(MeshEndpointSchema$1).readonly(),
5132
+ endpoints: z.array(MeshEndpointSchema).readonly(),
4884
5133
  /** Last error from the daemon, when not joined. */
4885
5134
  error: z.string().optional(),
4886
5135
  /**
@@ -4955,130 +5204,6 @@ authKey: z.string().optional() }), z.object({
4955
5204
  /** Human-readable error when `ok: false`. */
4956
5205
  error: z.string().optional()
4957
5206
  }), { kind: "mutation" });
4958
- var MeshEndpointSchema = z.object({
4959
- id: z.string(),
4960
- label: z.string(),
4961
- scope: z.enum(["mesh", "public"]),
4962
- url: z.string(),
4963
- hostname: z.string(),
4964
- port: z.number(),
4965
- protocol: z.enum(["http", "https"])
4966
- });
4967
- var MeshProviderInfoSchema = z.object({
4968
- /** Stable id matching the addon id. */
4969
- addonId: z.string(),
4970
- /** Display label shown on the admin row — sourced from the addon manifest. */
4971
- displayName: z.string(),
4972
- /** True when the host is joined to this provider's mesh. */
4973
- joined: z.boolean(),
4974
- /** Local mesh IP (empty when not joined). */
4975
- meshIp: z.string(),
4976
- /** MagicDNS / mesh hostname (empty when not configured). */
4977
- magicDnsHostname: z.string(),
4978
- /** Peer count (excluding self). */
4979
- peerCount: z.number(),
4980
- /** Active endpoints (mesh IP + MagicDNS + optional public Funnel). */
4981
- endpoints: z.array(MeshEndpointSchema).readonly(),
4982
- /** Last error reported by the provider. */
4983
- error: z.string().optional(),
4984
- /** Tenant / tailnet / network display name. Empty pre-join. */
4985
- tenantName: z.string(),
4986
- /** Mesh DNS suffix (e.g. tailXXXX.ts.net). Empty when not configured. */
4987
- magicDnsSuffix: z.string(),
4988
- /** Authenticated user / account login. Null for token-only providers. */
4989
- userLogin: z.string().nullable(),
4990
- /** Provider control-plane URL. */
4991
- controlPlaneUrl: z.string(),
4992
- /** Machine-key expiry (epoch ms). Null when keys don't rotate. */
4993
- keyExpiry: z.number().nullable()
4994
- });
4995
- method(z.void(), z.array(MeshProviderInfoSchema).readonly()), method(z.object({
4996
- addonId: z.string(),
4997
- authKey: z.string().min(8),
4998
- hostname: z.string().optional()
4999
- }), z.object({ joined: z.literal(true) }), { kind: "mutation" }), method(z.object({ addonId: z.string() }), z.object({ success: z.literal(true) }), { kind: "mutation" }), method(z.object({
5000
- addonId: z.string(),
5001
- hostname: z.string().optional()
5002
- }), z.object({ loginUrl: z.string() }), { kind: "mutation" }), method(z.object({ addonId: z.string() }), z.object({ loggedOut: z.literal(true) }), { kind: "mutation" }), method(z.object({ addonId: z.string() }), z.object({ peers: z.array(MeshPeerSchema).readonly() }));
5003
- var MethodAccessSchema = z.enum([
5004
- "view",
5005
- "create",
5006
- "delete"
5007
- ]);
5008
- var AllowedProviderSchema = z.union([z.literal("*"), z.array(z.string())]);
5009
- var AllowedDevicesSchema = z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]));
5010
- var CapScopeSchema = z.enum(["device", "system"]);
5011
- var TokenScopeSchema = z.discriminatedUnion("type", [
5012
- z.object({
5013
- type: z.literal("category"),
5014
- target: CapScopeSchema,
5015
- access: z.array(MethodAccessSchema).min(1)
5016
- }),
5017
- z.object({
5018
- type: z.literal("capability"),
5019
- target: z.string(),
5020
- access: z.array(MethodAccessSchema).min(1)
5021
- }),
5022
- z.object({
5023
- type: z.literal("addon"),
5024
- target: z.string(),
5025
- access: z.array(MethodAccessSchema).min(1)
5026
- }),
5027
- z.object({
5028
- type: z.literal("device"),
5029
- /**
5030
- * One or more deviceIds (serialised as strings for wire-format
5031
- * consistency with the rest of the union). Matcher accepts if
5032
- * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
5033
- * of one scope-per-device when granting access to a set of cameras.
5034
- */
5035
- targets: z.array(z.string()).min(1),
5036
- access: z.array(MethodAccessSchema).min(1)
5037
- })
5038
- ]);
5039
- z.object({
5040
- id: z.string(),
5041
- username: z.string(),
5042
- passwordHash: z.string(),
5043
- /**
5044
- * Admin bypass. When true, the middleware skips the scope-access
5045
- * check entirely. There is no other axis of privilege; the legacy
5046
- * role enum collapsed onto this boolean in v2.
5047
- */
5048
- isAdmin: z.boolean().default(false),
5049
- allowedProviders: AllowedProviderSchema,
5050
- allowedDevices: AllowedDevicesSchema,
5051
- /**
5052
- * Scopes granted to this user. Admins bypass; their `scopes` is
5053
- * ignored. Non-admins without scopes are locked out of every
5054
- * protected call.
5055
- */
5056
- scopes: z.array(TokenScopeSchema).default([]),
5057
- createdAt: z.number(),
5058
- updatedAt: z.number()
5059
- });
5060
- z.object({
5061
- id: z.string(),
5062
- label: z.string(),
5063
- isAdmin: z.boolean().default(false),
5064
- allowedProviders: AllowedProviderSchema,
5065
- allowedDevices: AllowedDevicesSchema,
5066
- tokenHash: z.string(),
5067
- tokenPrefix: z.string(),
5068
- createdAt: z.number(),
5069
- lastUsedAt: z.number().optional()
5070
- });
5071
- z.object({
5072
- id: z.string(),
5073
- userId: z.string(),
5074
- name: z.string(),
5075
- tokenHash: z.string(),
5076
- tokenPrefix: z.string(),
5077
- scopes: z.array(TokenScopeSchema),
5078
- expiresAt: z.number().nullish(),
5079
- lastUsedAt: z.number().nullish(),
5080
- createdAt: z.number()
5081
- });
5082
5207
  var UserSummarySchema = z.object({
5083
5208
  id: z.string(),
5084
5209
  username: z.string(),
@@ -5151,6 +5276,16 @@ var CreateScopedTokenResultSchema = z.object({
5151
5276
  token: z.string(),
5152
5277
  record: ScopedTokenSummarySchema
5153
5278
  });
5279
+ var OauthSessionSummarySchema = z.object({
5280
+ id: z.string(),
5281
+ userId: z.string(),
5282
+ username: z.string(),
5283
+ integrationId: z.string(),
5284
+ scopes: z.array(TokenScopeSchema),
5285
+ createdAt: z.number(),
5286
+ lastUsedAt: z.number(),
5287
+ revokedAt: z.number().nullable()
5288
+ });
5154
5289
  var TotpSetupResultSchema = z.object({
5155
5290
  secret: z.string(),
5156
5291
  otpauthUrl: z.string()
@@ -5233,6 +5368,41 @@ method(z.void(), z.array(UserSummarySchema), { auth: "admin" }), method(CreateUs
5233
5368
  }), z.object({ valid: z.boolean() }), {
5234
5369
  kind: "mutation",
5235
5370
  access: "view"
5371
+ }), method(z.object({
5372
+ integrationId: z.string(),
5373
+ userId: z.string(),
5374
+ username: z.string(),
5375
+ scopes: z.array(TokenScopeSchema),
5376
+ redirectUri: z.string(),
5377
+ hubUrl: z.string()
5378
+ }), z.object({ code: z.string() }), {
5379
+ kind: "mutation",
5380
+ access: "create"
5381
+ }), method(z.object({
5382
+ code: z.string(),
5383
+ redirectUri: z.string()
5384
+ }), z.object({
5385
+ accessToken: z.string(),
5386
+ refreshToken: z.string(),
5387
+ expiresIn: z.number()
5388
+ }).nullable(), {
5389
+ kind: "mutation",
5390
+ access: "view"
5391
+ }), method(z.object({ refreshToken: z.string() }), z.object({
5392
+ accessToken: z.string(),
5393
+ refreshToken: z.string(),
5394
+ expiresIn: z.number()
5395
+ }).nullable(), {
5396
+ kind: "mutation",
5397
+ access: "view"
5398
+ }), method(z.object({ token: z.string() }), z.object({
5399
+ userId: z.string(),
5400
+ username: z.string(),
5401
+ scopes: z.array(TokenScopeSchema)
5402
+ }).nullable(), { access: "view" }), method(z.void(), z.array(OauthSessionSummarySchema), { auth: "admin" }), method(z.object({ id: z.string() }), z.object({ success: z.boolean() }), {
5403
+ kind: "mutation",
5404
+ auth: "admin",
5405
+ access: "delete"
5236
5406
  });
5237
5407
  var FeatureManifestSchema = z.object({
5238
5408
  streaming: z.boolean(),
@@ -5401,7 +5571,13 @@ method(z.void(), z.array(TopologyNodeSchema).readonly(), { auth: "admin" }), met
5401
5571
  }), RenameNodeResultSchema, {
5402
5572
  kind: "mutation",
5403
5573
  auth: "admin"
5404
- }), method(z.void(), z.record(z.string(), ClusterAddonStatusEntrySchema), { auth: "admin" }), method(z.object({ nodeId: z.string() }), z.array(NodeAddonEntrySchema).readonly(), { auth: "admin" }), method(z.object({
5574
+ }), method(z.void(), z.record(z.string(), ClusterAddonStatusEntrySchema), { auth: "admin" }), method(z.object({ windowSeconds: z.number().int().positive().max(300).default(60) }), z.array(z.object({
5575
+ callerAddonId: z.string(),
5576
+ providerAddonId: z.string(),
5577
+ capName: z.string(),
5578
+ callsPerMin: z.number(),
5579
+ lastCallAtMs: z.number()
5580
+ })).readonly(), { auth: "admin" }), method(z.object({ nodeId: z.string() }), z.array(NodeAddonEntrySchema).readonly(), { auth: "admin" }), method(z.object({
5405
5581
  nodeId: z.string(),
5406
5582
  level: z.string()
5407
5583
  }), SuccessSchema, {
@@ -5689,6 +5865,13 @@ method(z.void(), z.array(AddonListItemSchema).readonly()), method(z.object({
5689
5865
  mode: z.enum(["singleton", "collection"]),
5690
5866
  isActive: z.boolean()
5691
5867
  })).readonly()), method(z.object({
5868
+ capName: z.string().min(1),
5869
+ addonId: z.string().min(1),
5870
+ enabled: z.boolean()
5871
+ }), z.object({ success: z.literal(true) }), {
5872
+ kind: "mutation",
5873
+ auth: "admin"
5874
+ }), method(z.object({
5692
5875
  packageName: z.string().min(1),
5693
5876
  version: z.string().optional()
5694
5877
  }), UpdateFrameworkPackageResultSchema, {
@@ -7632,6 +7815,16 @@ var StorageManager = class {
7632
7815
  }
7633
7816
  };
7634
7817
  //#endregion
7818
+ //#region src/auth/scope-matcher.ts
7819
+ /**
7820
+ * True if the scope set grants `access` on device-scoped capabilities.
7821
+ * A `category:device` grant covers every device cap (the broad grant).
7822
+ * Mirrors the OR-semantics of the existing token scope matcher.
7823
+ */
7824
+ function scopesAllowDeviceCap(scopes, access) {
7825
+ return scopes.some((s) => s.type === "category" && s.target === "device" && s.access.includes(access));
7826
+ }
7827
+ //#endregion
7635
7828
  //#region src/notification/notification-service.ts
7636
7829
  /**
7637
7830
  * Central notification service that routes notifications to configured outputs.
@@ -8384,6 +8577,6 @@ var IntegrationRegistry = class {
8384
8577
  }
8385
8578
  };
8386
8579
  //#endregion
8387
- export { AddonApiFactory, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CORE_TABLE_DDL, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, DeviceManagerAddon, DeviceStore, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FsStorageBackend, HubForwarderAddon, HubForwarderDestination, IntegrationRegistry, LifecycleStateMachine, LocalAuthAddon, LogManager, LogRingBuffer, ModelDownloadService, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, ReplEngine, ScopedLogger, ScopedTokenManager, SettingsStore, SqliteSettingsAddon, SqliteSettingsBackend, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UserManager, WinstonDestination, WinstonLoggingAddon, addonTableToDdl, buildBinaryPath, deleteModelFromDisk, downloadBinary, downloadFile, downloadModel, ensureBinary, ensureFfmpeg, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getFfmpegDownloadUrl, getModelFilePath, getPidStats, getPlatformInfo, getPythonDownloadUrl, getSinglePidStats, installPythonPackages, installPythonRequirements, isModelDownloaded, loadTlsCert };
8580
+ export { AddonApiFactory, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CORE_TABLE_DDL, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, DeviceManagerAddon, DeviceStore, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FsStorageBackend, HubForwarderAddon, HubForwarderDestination, IntegrationRegistry, LifecycleStateMachine, LocalAuthAddon, LogManager, LogRingBuffer, ModelDownloadService, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, ReplEngine, ScopedLogger, ScopedTokenManager, SettingsStore, SqliteSettingsAddon, SqliteSettingsBackend, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UserManager, WinstonDestination, WinstonLoggingAddon, addonTableToDdl, buildBinaryPath, deleteModelFromDisk, downloadBinary, downloadFile, downloadModel, ensureBinary, ensureFfmpeg, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getFfmpegDownloadUrl, getModelFilePath, getPidStats, getPlatformInfo, getPythonDownloadUrl, getSinglePidStats, installPythonPackages, installPythonRequirements, isModelDownloaded, loadTlsCert, scopesAllowDeviceCap };
8388
8581
 
8389
8582
  //# sourceMappingURL=index.mjs.map