@camstack/core 0.1.38 → 0.1.40

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 (52) 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 +17 -0
  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 +95 -5
  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 +95 -5
  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 +419 -97
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.mjs +419 -98
  51. package/dist/index.mjs.map +1 -1
  52. package/package.json +19 -1
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ let node_vm = require("node:vm");
37
37
  node_vm = require_chunk.__toESM(node_vm);
38
38
  let node_os = require("node:os");
39
39
  node_os = require_chunk.__toESM(node_os);
40
- //#region ../types/dist/index-CWhQOnm9.mjs
40
+ //#region ../types/dist/index-CgPd35k5.mjs
41
41
  var MODEL_FORMATS = [
42
42
  "onnx",
43
43
  "coreml",
@@ -112,6 +112,12 @@ Object.fromEntries([
112
112
  icon: "video",
113
113
  order: 35
114
114
  },
115
+ {
116
+ id: "ptz",
117
+ label: "PTZ",
118
+ icon: "move",
119
+ order: 40
120
+ },
115
121
  {
116
122
  id: "pipeline",
117
123
  label: "Detection Pipeline",
@@ -238,7 +244,19 @@ var DecoderSessionConfigSchema = zod.z.object({
238
244
  * on every line so `grep tag=broker:5/high` filters one camera
239
245
  * profile cleanly.
240
246
  */
241
- tag: zod.z.string().optional()
247
+ tag: zod.z.string().optional(),
248
+ /**
249
+ * Where the session delivers decoded frames (Phase 5 / D9):
250
+ *
251
+ * - `'callback'` (default) — the legacy pixel path: decoded frames are
252
+ * buffered as `DecodedFrame`s and drained via `pullFrames`.
253
+ * - `'shm'` — the shared-memory frame plane: decoded frames are written
254
+ * into an OS shared-memory ring and drained as zero-pixel
255
+ * `FrameHandle`s via `pullHandles`. A session is one mode or the
256
+ * other — `pullFrames` returns nothing for an `'shm'` session and
257
+ * `pullHandles` returns nothing for a `'callback'` session.
258
+ */
259
+ frameSink: zod.z.enum(["callback", "shm"]).default("callback")
242
260
  });
243
261
  function errMsg$2(err) {
244
262
  if (err instanceof Error) return err.message;
@@ -898,6 +916,63 @@ var DecodedFrameSchema = zod.z.object({
898
916
  ]),
899
917
  timestamp: zod.z.number()
900
918
  });
919
+ var FrameHandleSchema = zod.z.object({
920
+ shmId: zod.z.string(),
921
+ slot: zod.z.number().int().nonnegative(),
922
+ seq: zod.z.number().int().nonnegative(),
923
+ width: zod.z.number().int().positive(),
924
+ height: zod.z.number().int().positive(),
925
+ format: zod.z.enum([
926
+ "jpeg",
927
+ "rgb",
928
+ "bgr",
929
+ "yuv420",
930
+ "gray"
931
+ ]),
932
+ pts: zod.z.number(),
933
+ byteLength: zod.z.number().int().nonnegative(),
934
+ nodeId: zod.z.string(),
935
+ slotCount: zod.z.number().int().positive()
936
+ });
937
+ var FrameHandleFormatSchema = zod.z.enum([
938
+ "rgb",
939
+ "bgr",
940
+ "yuv420",
941
+ "gray"
942
+ ]);
943
+ var SubscribeFramesInputSchema = zod.z.object({
944
+ brokerId: zod.z.string(),
945
+ format: FrameHandleFormatSchema,
946
+ /**
947
+ * Optional reader-side cadence hint in frames per second. The broker does
948
+ * NOT throttle — latest-wins ring reads drop frames implicitly for a slow
949
+ * consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
950
+ * the consumer can pace its own `pullFrameHandles` polling.
951
+ */
952
+ maxFps: zod.z.number().positive().optional(),
953
+ /** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
954
+ tag: zod.z.string().optional()
955
+ });
956
+ var SubscribeFramesResultSchema = zod.z.object({
957
+ /** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
958
+ subscriptionId: zod.z.string(),
959
+ /** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
960
+ maxFps: zod.z.number().nonnegative()
961
+ });
962
+ var DecodedAudioChunkSchema = zod.z.object({
963
+ data: zod.z.instanceof(Uint8Array),
964
+ sampleRate: zod.z.number().int().positive(),
965
+ channels: zod.z.number().int().positive(),
966
+ timestamp: zod.z.number()
967
+ });
968
+ var SubscribeAudioChunksInputSchema = zod.z.object({
969
+ brokerId: zod.z.string(),
970
+ /** Short caller-identity tag (`audio-analyzer`, …) for `listClients`. */
971
+ tag: zod.z.string().optional()
972
+ });
973
+ var SubscribeAudioChunksResultSchema = zod.z.object({
974
+ /** Opaque id passed to `pullAudioChunks` / `unsubscribeAudioChunks`. */
975
+ subscriptionId: zod.z.string() });
901
976
  var BrokerStatusSchema$1 = zod.z.enum([
902
977
  "idle",
903
978
  "connecting",
@@ -1100,7 +1175,13 @@ method(zod.z.object({
1100
1175
  }), {
1101
1176
  kind: "mutation",
1102
1177
  auth: "admin"
1103
- }), method(zod.z.object({ brokerId: zod.z.string() }), zod.z.custom()), method(zod.z.object({
1178
+ }), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(zod.z.object({
1179
+ subscriptionId: zod.z.string(),
1180
+ maxCount: zod.z.number().int().positive().default(8)
1181
+ }), zod.z.array(DecodedAudioChunkSchema).readonly()), method(zod.z.object({ subscriptionId: zod.z.string() }), zod.z.object({ released: zod.z.boolean() }), { kind: "mutation" }), method(SubscribeFramesInputSchema, SubscribeFramesResultSchema, { kind: "mutation" }), method(zod.z.object({
1182
+ subscriptionId: zod.z.string(),
1183
+ maxCount: zod.z.number().int().positive().default(4)
1184
+ }), zod.z.array(FrameHandleSchema).readonly()), method(zod.z.object({ subscriptionId: zod.z.string() }), zod.z.object({ released: zod.z.boolean() }), { kind: "mutation" }), method(zod.z.object({
1104
1185
  brokerId: zod.z.string(),
1105
1186
  seconds: zod.z.number().min(0).max(30)
1106
1187
  }), zod.z.void(), {
@@ -1793,6 +1874,34 @@ DeviceType.Light, DeviceType.Siren, DeviceType.Switch, method(zod.z.object({
1793
1874
  enabled: zod.z.boolean(),
1794
1875
  lastChangedAt: zod.z.number()
1795
1876
  });
1877
+ zod.z.object({
1878
+ enabled: zod.z.boolean(),
1879
+ sensitivity: zod.z.number(),
1880
+ /** Row-major active-cell grid. Length = gridWidth*gridHeight (see getOptions). */
1881
+ cells: zod.z.array(zod.z.boolean()),
1882
+ lastFetchedAt: zod.z.number()
1883
+ });
1884
+ var MotionZoneOptionsSchema = zod.z.object({
1885
+ gridWidth: zod.z.number(),
1886
+ gridHeight: zod.z.number(),
1887
+ sensitivity: zod.z.object({
1888
+ min: zod.z.number(),
1889
+ max: zod.z.number(),
1890
+ step: zod.z.number()
1891
+ })
1892
+ });
1893
+ var MotionZonePatchSchema = zod.z.object({
1894
+ enabled: zod.z.boolean().optional(),
1895
+ sensitivity: zod.z.number().optional(),
1896
+ cells: zod.z.array(zod.z.boolean()).optional()
1897
+ });
1898
+ DeviceType.Camera, method(zod.z.object({ deviceId: zod.z.number() }), MotionZoneOptionsSchema), method(zod.z.object({
1899
+ deviceId: zod.z.number(),
1900
+ patch: MotionZonePatchSchema
1901
+ }), zod.z.void(), {
1902
+ kind: "mutation",
1903
+ auth: "admin"
1904
+ });
1796
1905
  var AutotrackTargetTypeSchema = zod.z.string().describe("Vendor target string (people/vehicle/pet); empty = camera default");
1797
1906
  var PtzAutotrackSettingsSchema = zod.z.object({
1798
1907
  targetType: AutotrackTargetTypeSchema,
@@ -1835,6 +1944,85 @@ DeviceType.Camera, method(zod.z.object({ deviceId: zod.z.number() }), PtzAutotra
1835
1944
  deviceId: zod.z.number(),
1836
1945
  status: PtzAutotrackStatusSchema
1837
1946
  });
1947
+ var StreamProfileSchema = zod.z.enum([
1948
+ "main",
1949
+ "sub",
1950
+ "ext"
1951
+ ]);
1952
+ var StreamProfileConfigSchema = zod.z.object({
1953
+ width: zod.z.number(),
1954
+ height: zod.z.number(),
1955
+ codec: zod.z.enum(["h264", "h265"]),
1956
+ framerate: zod.z.number(),
1957
+ bitrate: zod.z.number(),
1958
+ bitrateMode: zod.z.enum(["vbr", "cbr"]).optional(),
1959
+ encoderProfile: zod.z.enum([
1960
+ "high",
1961
+ "main",
1962
+ "baseline"
1963
+ ]).optional(),
1964
+ gop: zod.z.number().optional(),
1965
+ audio: zod.z.boolean().optional()
1966
+ });
1967
+ zod.z.object({
1968
+ /** Per-profile current config. A profile absent = the camera doesn't have it. */
1969
+ main: StreamProfileConfigSchema.optional(),
1970
+ sub: StreamProfileConfigSchema.optional(),
1971
+ ext: StreamProfileConfigSchema.optional(),
1972
+ lastFetchedAt: zod.z.number()
1973
+ });
1974
+ var StreamProfileOptionsSchema = zod.z.object({
1975
+ resolutions: zod.z.array(zod.z.object({
1976
+ width: zod.z.number(),
1977
+ height: zod.z.number()
1978
+ })),
1979
+ codecs: zod.z.array(zod.z.enum(["h264", "h265"])),
1980
+ framerates: zod.z.array(zod.z.number()),
1981
+ /** Allowed bitrate values (kbps). Empty if the camera takes a free range. */
1982
+ bitrates: zod.z.array(zod.z.number()),
1983
+ /** Optional [min,max] kbps when the camera accepts a continuous range. */
1984
+ bitrateRange: zod.z.tuple([zod.z.number(), zod.z.number()]).optional(),
1985
+ supportsBitrateMode: zod.z.boolean(),
1986
+ supportsEncoderProfile: zod.z.boolean(),
1987
+ supportsGop: zod.z.boolean(),
1988
+ /** Allowed GOP / keyframe-interval range, in seconds — drives the
1989
+ * I-frame-interval selector. Absent when the camera advertises GOP
1990
+ * support but no concrete range (callers then fall back to a free
1991
+ * numeric input). `{ min, max, step }` per the getOptions convention. */
1992
+ gop: zod.z.object({
1993
+ min: zod.z.number(),
1994
+ max: zod.z.number(),
1995
+ step: zod.z.number()
1996
+ }).optional()
1997
+ });
1998
+ var StreamParamsOptionsSchema = zod.z.object({
1999
+ main: StreamProfileOptionsSchema.optional(),
2000
+ sub: StreamProfileOptionsSchema.optional(),
2001
+ ext: StreamProfileOptionsSchema.optional()
2002
+ });
2003
+ var StreamProfilePatchSchema = zod.z.object({
2004
+ width: zod.z.number().optional(),
2005
+ height: zod.z.number().optional(),
2006
+ codec: zod.z.enum(["h264", "h265"]).optional(),
2007
+ framerate: zod.z.number().optional(),
2008
+ bitrate: zod.z.number().optional(),
2009
+ bitrateMode: zod.z.enum(["vbr", "cbr"]).optional(),
2010
+ encoderProfile: zod.z.enum([
2011
+ "high",
2012
+ "main",
2013
+ "baseline"
2014
+ ]).optional(),
2015
+ gop: zod.z.number().optional(),
2016
+ audio: zod.z.boolean().optional()
2017
+ });
2018
+ DeviceType.Camera, method(zod.z.object({ deviceId: zod.z.number() }), StreamParamsOptionsSchema), method(zod.z.object({
2019
+ deviceId: zod.z.number(),
2020
+ profile: StreamProfileSchema,
2021
+ patch: StreamProfilePatchSchema
2022
+ }), zod.z.void(), {
2023
+ kind: "mutation",
2024
+ auth: "admin"
2025
+ }), method(zod.z.object({ deviceId: zod.z.number() }), zod.z.unknown().nullable());
1838
2026
  zod.z.object({
1839
2027
  on: zod.z.boolean(),
1840
2028
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
@@ -2474,6 +2662,85 @@ method(LogEntrySchema, zod.z.void(), { kind: "mutation" }), method(zod.z.object(
2474
2662
  var StaticDirOutputSchema = zod.z.object({ staticDir: zod.z.string() });
2475
2663
  var VersionOutputSchema = zod.z.object({ version: zod.z.string() });
2476
2664
  method(zod.z.void(), StaticDirOutputSchema), method(zod.z.void(), VersionOutputSchema);
2665
+ var MethodAccessSchema = zod.z.enum([
2666
+ "view",
2667
+ "create",
2668
+ "delete"
2669
+ ]);
2670
+ var AllowedProviderSchema = zod.z.union([zod.z.literal("*"), zod.z.array(zod.z.string())]);
2671
+ var AllowedDevicesSchema = zod.z.record(zod.z.string(), zod.z.union([zod.z.literal("*"), zod.z.array(zod.z.string())]));
2672
+ var CapScopeSchema = zod.z.enum(["device", "system"]);
2673
+ var TokenScopeSchema = zod.z.discriminatedUnion("type", [
2674
+ zod.z.object({
2675
+ type: zod.z.literal("category"),
2676
+ target: CapScopeSchema,
2677
+ access: zod.z.array(MethodAccessSchema).min(1)
2678
+ }),
2679
+ zod.z.object({
2680
+ type: zod.z.literal("capability"),
2681
+ target: zod.z.string(),
2682
+ access: zod.z.array(MethodAccessSchema).min(1)
2683
+ }),
2684
+ zod.z.object({
2685
+ type: zod.z.literal("addon"),
2686
+ target: zod.z.string(),
2687
+ access: zod.z.array(MethodAccessSchema).min(1)
2688
+ }),
2689
+ zod.z.object({
2690
+ type: zod.z.literal("device"),
2691
+ /**
2692
+ * One or more deviceIds (serialised as strings for wire-format
2693
+ * consistency with the rest of the union). Matcher accepts if
2694
+ * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
2695
+ * of one scope-per-device when granting access to a set of cameras.
2696
+ */
2697
+ targets: zod.z.array(zod.z.string()).min(1),
2698
+ access: zod.z.array(MethodAccessSchema).min(1)
2699
+ })
2700
+ ]);
2701
+ zod.z.object({
2702
+ id: zod.z.string(),
2703
+ username: zod.z.string(),
2704
+ passwordHash: zod.z.string(),
2705
+ /**
2706
+ * Admin bypass. When true, the middleware skips the scope-access
2707
+ * check entirely. There is no other axis of privilege; the legacy
2708
+ * role enum collapsed onto this boolean in v2.
2709
+ */
2710
+ isAdmin: zod.z.boolean().default(false),
2711
+ allowedProviders: AllowedProviderSchema,
2712
+ allowedDevices: AllowedDevicesSchema,
2713
+ /**
2714
+ * Scopes granted to this user. Admins bypass; their `scopes` is
2715
+ * ignored. Non-admins without scopes are locked out of every
2716
+ * protected call.
2717
+ */
2718
+ scopes: zod.z.array(TokenScopeSchema).default([]),
2719
+ createdAt: zod.z.number(),
2720
+ updatedAt: zod.z.number()
2721
+ });
2722
+ zod.z.object({
2723
+ id: zod.z.string(),
2724
+ label: zod.z.string(),
2725
+ isAdmin: zod.z.boolean().default(false),
2726
+ allowedProviders: AllowedProviderSchema,
2727
+ allowedDevices: AllowedDevicesSchema,
2728
+ tokenHash: zod.z.string(),
2729
+ tokenPrefix: zod.z.string(),
2730
+ createdAt: zod.z.number(),
2731
+ lastUsedAt: zod.z.number().optional()
2732
+ });
2733
+ zod.z.object({
2734
+ id: zod.z.string(),
2735
+ userId: zod.z.string(),
2736
+ name: zod.z.string(),
2737
+ tokenHash: zod.z.string(),
2738
+ tokenPrefix: zod.z.string(),
2739
+ scopes: zod.z.array(TokenScopeSchema),
2740
+ expiresAt: zod.z.number().nullish(),
2741
+ lastUsedAt: zod.z.number().nullish(),
2742
+ createdAt: zod.z.number()
2743
+ });
2477
2744
  var SsoBridgeClaimsSchema = zod.z.object({
2478
2745
  userId: zod.z.string(),
2479
2746
  username: zod.z.string(),
@@ -2489,12 +2756,36 @@ var SsoBridgeClaimsSchema = zod.z.object({
2489
2756
  * JWT WITHOUT verifying the signature — the hub re-verifies on every
2490
2757
  * inbound call so trust still rests with the signing hub.
2491
2758
  */
2492
- hubUrl: zod.z.string().optional()
2759
+ hubUrl: zod.z.string().optional(),
2760
+ /** Permission scopes baked into the token. Set by the OAuth
2761
+ * account-linking grant; absent on ordinary SSO-login tokens. */
2762
+ scopes: zod.z.array(TokenScopeSchema).optional(),
2763
+ /** OAuth authorization-code binding — set only on `oauth-code` tokens. */
2764
+ redirectUri: zod.z.string().optional(),
2765
+ integrationId: zod.z.string().optional(),
2766
+ /** JWT ID — unique per issued code; consumed-set enforces single-use. */
2767
+ jti: zod.z.string().optional(),
2768
+ /** OAuth session registry id — set on `oauth-access`/`oauth-refresh`
2769
+ * tokens so the verify path can check the session is not revoked. */
2770
+ sessionId: zod.z.string().optional()
2493
2771
  });
2494
2772
  method(zod.z.object({
2495
2773
  claims: SsoBridgeClaimsSchema,
2496
2774
  ttlSec: zod.z.number().int().positive().optional()
2497
2775
  }), zod.z.object({ token: zod.z.string() })), method(zod.z.object({ token: zod.z.string() }), SsoBridgeClaimsSchema.nullable());
2776
+ var OauthIntegrationDescriptorSchema = zod.z.object({
2777
+ /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
2778
+ integrationId: zod.z.string(),
2779
+ /** Human label rendered on the consent page. */
2780
+ displayName: zod.z.string(),
2781
+ /** Scopes baked into every token issued for this integration. */
2782
+ requestedScopes: zod.z.array(TokenScopeSchema),
2783
+ /** Allowed redirect_uri prefixes. /api/oauth2/authorize rejects any
2784
+ * redirect_uri that does not start with one of these. Required —
2785
+ * an empty list means the integration can never complete linking. */
2786
+ allowedRedirectPrefixes: zod.z.array(zod.z.string()).min(1)
2787
+ });
2788
+ method(zod.z.void(), OauthIntegrationDescriptorSchema);
2498
2789
  var PasskeySummarySchema = zod.z.object({
2499
2790
  credentialId: zod.z.string(),
2500
2791
  label: zod.z.string(),
@@ -2740,22 +3031,29 @@ var WidgetSizeEnum = zod.z.enum([
2740
3031
  "lg",
2741
3032
  "xl"
2742
3033
  ]);
3034
+ var WidgetRemoteSchema = zod.z.object({
3035
+ remoteName: zod.z.string(),
3036
+ exposedModule: zod.z.string(),
3037
+ componentKey: zod.z.string().optional()
3038
+ });
2743
3039
  var WidgetMetadataSchema = zod.z.object({
2744
- /** Stable id within the addon kebab-case. */
2745
- stableId: zod.z.string(),
3040
+ /** Primary host tab `'dashboard'`, `'device-tab'`, or a device-detail tab id. */
3041
+ tab: zod.z.string(),
3042
+ /** Optional sub-tab within `tab`. */
3043
+ subTab: zod.z.string().optional(),
2746
3044
  /** Operator-facing label. */
2747
3045
  label: zod.z.string(),
3046
+ /** Ordering within `(tab, subTab)`, ascending. */
3047
+ order: zod.z.number().optional(),
3048
+ /** Always `'remote'` — a widget is a Module Federation remote. */
3049
+ kind: zod.z.literal("remote"),
3050
+ /** MF remote descriptor. */
3051
+ remote: WidgetRemoteSchema,
3052
+ /** Stable id within the addon — kebab-case. Equals `remote.componentKey`. */
3053
+ stableId: zod.z.string(),
2748
3054
  description: zod.z.string().optional(),
2749
3055
  icon: zod.z.string().optional(),
2750
3056
  /**
2751
- * Module Federation remote name — must match the `name` field on the
2752
- * widget addon's `federation()` plugin config. Used by the host's
2753
- * `<WidgetRegistryProvider>` to call `loadRemote('<remoteName>/widgets')`.
2754
- * Conventionally `addon_<addonid>_widgets` (snake_case; MF names
2755
- * cannot contain hyphens).
2756
- */
2757
- remoteName: zod.z.string(),
2758
- /**
2759
3057
  * Bundle filename inside the addon's `dist/` dir served at
2760
3058
  * `/api/addon-widgets/<addonId>/<bundle>`. With Module Federation
2761
3059
  * this is always `'remoteEntry.js'` — the value is kept on the
@@ -2763,9 +3061,9 @@ var WidgetMetadataSchema = zod.z.object({
2763
3061
  * cache-buster URL without a separate filesystem stat.
2764
3062
  */
2765
3063
  bundle: zod.z.string(),
2766
- /** Where the widget makes sense to render. */
3064
+ /** Every host the widget supports. The picker filters on this set. */
2767
3065
  hosts: zod.z.array(WidgetHostEnum).readonly(),
2768
- /** Required props the host must supply. Validated at <WidgetSlot> mount. */
3066
+ /** Required props the host must supply. Validated at `<WidgetSlot>` mount. */
2769
3067
  requires: zod.z.object({
2770
3068
  deviceContext: zod.z.boolean().default(false),
2771
3069
  integrationContext: zod.z.boolean().default(false)
@@ -2829,6 +3127,16 @@ var InvokeReplyEnvelopeSchema = zod.z.object({
2829
3127
  contentType: zod.z.string().optional()
2830
3128
  });
2831
3129
  method(zod.z.void(), zod.z.array(AddonHttpRouteSchema)), method(InvokeRequestSchema, InvokeReplyEnvelopeSchema, { kind: "mutation" });
3130
+ var ShmRingStatsSchema = zod.z.object({
3131
+ sessionId: zod.z.string(),
3132
+ slotCount: zod.z.number().int(),
3133
+ slotByteLength: zod.z.number().int(),
3134
+ segmentBytes: zod.z.number().int(),
3135
+ budgetMb: zod.z.number().int(),
3136
+ framesWritten: zod.z.number().int(),
3137
+ getFrameHits: zod.z.number().int(),
3138
+ getFrameMisses: zod.z.number().int()
3139
+ });
2832
3140
  method(zod.z.object({ codec: zod.z.string() }), zod.z.boolean()), method(zod.z.void(), zod.z.object({
2833
3141
  id: zod.z.string(),
2834
3142
  name: zod.z.string(),
@@ -2847,6 +3155,9 @@ method(zod.z.object({ codec: zod.z.string() }), zod.z.boolean()), method(zod.z.v
2847
3155
  sessionId: zod.z.string(),
2848
3156
  maxCount: zod.z.number().default(1)
2849
3157
  }), zod.z.array(DecodedFrameSchema)), method(zod.z.object({
3158
+ sessionId: zod.z.string(),
3159
+ maxCount: zod.z.number().default(1)
3160
+ }), zod.z.array(FrameHandleSchema)), method(zod.z.object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(zod.z.object({ sessionId: zod.z.string() }), ShmRingStatsSchema.nullable()), method(zod.z.object({
2850
3161
  sessionId: zod.z.string(),
2851
3162
  config: DecoderSessionConfigSchema.partial()
2852
3163
  }), zod.z.void()), method(zod.z.object({ sessionId: zod.z.string() }), DecoderStatsSchema), method(zod.z.void(), zod.z.array(zod.z.object({
@@ -4225,10 +4536,38 @@ var PtzMoveCommandSchema = zod.z.object({
4225
4536
  zoom: zod.z.number().optional(),
4226
4537
  speed: zod.z.number().optional()
4227
4538
  });
4539
+ PtzPositionSchema.extend({ autofocus: zod.z.boolean() });
4540
+ var PtzOptionsSchema = zod.z.object({
4541
+ hasPan: zod.z.boolean(),
4542
+ hasTilt: zod.z.boolean(),
4543
+ hasZoom: zod.z.boolean(),
4544
+ supportsPresets: zod.z.boolean(),
4545
+ /** Max number of named presets the camera supports, when known. */
4546
+ maxPresets: zod.z.number().optional(),
4547
+ /** Whether the camera exposes a controllable autofocus toggle
4548
+ * (boolean `hasX` per the getOptions availability convention). */
4549
+ hasAutofocus: zod.z.boolean()
4550
+ });
4228
4551
  DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: zod.z.number() }), zod.z.void(), { kind: "mutation" }), method(PtzMoveCommandSchema.extend({ deviceId: zod.z.number() }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(PtzPresetSchema)), method(zod.z.object({
4229
4552
  deviceId: zod.z.number(),
4230
4553
  presetId: zod.z.string()
4231
- }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({ deviceId: zod.z.number() }), PtzPositionSchema);
4554
+ }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({
4555
+ deviceId: zod.z.number(),
4556
+ presetId: zod.z.string(),
4557
+ name: zod.z.string()
4558
+ }), zod.z.void(), {
4559
+ kind: "mutation",
4560
+ auth: "admin"
4561
+ }), method(zod.z.object({
4562
+ deviceId: zod.z.number(),
4563
+ presetId: zod.z.string()
4564
+ }), zod.z.void(), {
4565
+ kind: "mutation",
4566
+ auth: "admin"
4567
+ }), method(zod.z.object({ deviceId: zod.z.number() }), PtzOptionsSchema), method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), { kind: "mutation" }), method(zod.z.object({ deviceId: zod.z.number() }), PtzPositionSchema), method(zod.z.object({
4568
+ deviceId: zod.z.number(),
4569
+ enabled: zod.z.boolean()
4570
+ }), zod.z.void(), { kind: "mutation" });
4232
4571
  var EventItemSchema = zod.z.object({
4233
4572
  id: zod.z.string(),
4234
4573
  type: zod.z.string(),
@@ -4871,85 +5210,6 @@ authKey: zod.z.string().optional() }), zod.z.object({
4871
5210
  /** Human-readable error when `ok: false`. */
4872
5211
  error: zod.z.string().optional()
4873
5212
  }), { kind: "mutation" });
4874
- var MethodAccessSchema = zod.z.enum([
4875
- "view",
4876
- "create",
4877
- "delete"
4878
- ]);
4879
- var AllowedProviderSchema = zod.z.union([zod.z.literal("*"), zod.z.array(zod.z.string())]);
4880
- var AllowedDevicesSchema = zod.z.record(zod.z.string(), zod.z.union([zod.z.literal("*"), zod.z.array(zod.z.string())]));
4881
- var CapScopeSchema = zod.z.enum(["device", "system"]);
4882
- var TokenScopeSchema = zod.z.discriminatedUnion("type", [
4883
- zod.z.object({
4884
- type: zod.z.literal("category"),
4885
- target: CapScopeSchema,
4886
- access: zod.z.array(MethodAccessSchema).min(1)
4887
- }),
4888
- zod.z.object({
4889
- type: zod.z.literal("capability"),
4890
- target: zod.z.string(),
4891
- access: zod.z.array(MethodAccessSchema).min(1)
4892
- }),
4893
- zod.z.object({
4894
- type: zod.z.literal("addon"),
4895
- target: zod.z.string(),
4896
- access: zod.z.array(MethodAccessSchema).min(1)
4897
- }),
4898
- zod.z.object({
4899
- type: zod.z.literal("device"),
4900
- /**
4901
- * One or more deviceIds (serialised as strings for wire-format
4902
- * consistency with the rest of the union). Matcher accepts if
4903
- * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
4904
- * of one scope-per-device when granting access to a set of cameras.
4905
- */
4906
- targets: zod.z.array(zod.z.string()).min(1),
4907
- access: zod.z.array(MethodAccessSchema).min(1)
4908
- })
4909
- ]);
4910
- zod.z.object({
4911
- id: zod.z.string(),
4912
- username: zod.z.string(),
4913
- passwordHash: zod.z.string(),
4914
- /**
4915
- * Admin bypass. When true, the middleware skips the scope-access
4916
- * check entirely. There is no other axis of privilege; the legacy
4917
- * role enum collapsed onto this boolean in v2.
4918
- */
4919
- isAdmin: zod.z.boolean().default(false),
4920
- allowedProviders: AllowedProviderSchema,
4921
- allowedDevices: AllowedDevicesSchema,
4922
- /**
4923
- * Scopes granted to this user. Admins bypass; their `scopes` is
4924
- * ignored. Non-admins without scopes are locked out of every
4925
- * protected call.
4926
- */
4927
- scopes: zod.z.array(TokenScopeSchema).default([]),
4928
- createdAt: zod.z.number(),
4929
- updatedAt: zod.z.number()
4930
- });
4931
- zod.z.object({
4932
- id: zod.z.string(),
4933
- label: zod.z.string(),
4934
- isAdmin: zod.z.boolean().default(false),
4935
- allowedProviders: AllowedProviderSchema,
4936
- allowedDevices: AllowedDevicesSchema,
4937
- tokenHash: zod.z.string(),
4938
- tokenPrefix: zod.z.string(),
4939
- createdAt: zod.z.number(),
4940
- lastUsedAt: zod.z.number().optional()
4941
- });
4942
- zod.z.object({
4943
- id: zod.z.string(),
4944
- userId: zod.z.string(),
4945
- name: zod.z.string(),
4946
- tokenHash: zod.z.string(),
4947
- tokenPrefix: zod.z.string(),
4948
- scopes: zod.z.array(TokenScopeSchema),
4949
- expiresAt: zod.z.number().nullish(),
4950
- lastUsedAt: zod.z.number().nullish(),
4951
- createdAt: zod.z.number()
4952
- });
4953
5213
  var UserSummarySchema = zod.z.object({
4954
5214
  id: zod.z.string(),
4955
5215
  username: zod.z.string(),
@@ -5022,6 +5282,16 @@ var CreateScopedTokenResultSchema = zod.z.object({
5022
5282
  token: zod.z.string(),
5023
5283
  record: ScopedTokenSummarySchema
5024
5284
  });
5285
+ var OauthSessionSummarySchema = zod.z.object({
5286
+ id: zod.z.string(),
5287
+ userId: zod.z.string(),
5288
+ username: zod.z.string(),
5289
+ integrationId: zod.z.string(),
5290
+ scopes: zod.z.array(TokenScopeSchema),
5291
+ createdAt: zod.z.number(),
5292
+ lastUsedAt: zod.z.number(),
5293
+ revokedAt: zod.z.number().nullable()
5294
+ });
5025
5295
  var TotpSetupResultSchema = zod.z.object({
5026
5296
  secret: zod.z.string(),
5027
5297
  otpauthUrl: zod.z.string()
@@ -5104,6 +5374,41 @@ method(zod.z.void(), zod.z.array(UserSummarySchema), { auth: "admin" }), method(
5104
5374
  }), zod.z.object({ valid: zod.z.boolean() }), {
5105
5375
  kind: "mutation",
5106
5376
  access: "view"
5377
+ }), method(zod.z.object({
5378
+ integrationId: zod.z.string(),
5379
+ userId: zod.z.string(),
5380
+ username: zod.z.string(),
5381
+ scopes: zod.z.array(TokenScopeSchema),
5382
+ redirectUri: zod.z.string(),
5383
+ hubUrl: zod.z.string()
5384
+ }), zod.z.object({ code: zod.z.string() }), {
5385
+ kind: "mutation",
5386
+ access: "create"
5387
+ }), method(zod.z.object({
5388
+ code: zod.z.string(),
5389
+ redirectUri: zod.z.string()
5390
+ }), zod.z.object({
5391
+ accessToken: zod.z.string(),
5392
+ refreshToken: zod.z.string(),
5393
+ expiresIn: zod.z.number()
5394
+ }).nullable(), {
5395
+ kind: "mutation",
5396
+ access: "view"
5397
+ }), method(zod.z.object({ refreshToken: zod.z.string() }), zod.z.object({
5398
+ accessToken: zod.z.string(),
5399
+ refreshToken: zod.z.string(),
5400
+ expiresIn: zod.z.number()
5401
+ }).nullable(), {
5402
+ kind: "mutation",
5403
+ access: "view"
5404
+ }), method(zod.z.object({ token: zod.z.string() }), zod.z.object({
5405
+ userId: zod.z.string(),
5406
+ username: zod.z.string(),
5407
+ scopes: zod.z.array(TokenScopeSchema)
5408
+ }).nullable(), { access: "view" }), method(zod.z.void(), zod.z.array(OauthSessionSummarySchema), { auth: "admin" }), method(zod.z.object({ id: zod.z.string() }), zod.z.object({ success: zod.z.boolean() }), {
5409
+ kind: "mutation",
5410
+ auth: "admin",
5411
+ access: "delete"
5107
5412
  });
5108
5413
  var FeatureManifestSchema = zod.z.object({
5109
5414
  streaming: zod.z.boolean(),
@@ -5272,7 +5577,13 @@ method(zod.z.void(), zod.z.array(TopologyNodeSchema).readonly(), { auth: "admin"
5272
5577
  }), RenameNodeResultSchema, {
5273
5578
  kind: "mutation",
5274
5579
  auth: "admin"
5275
- }), method(zod.z.void(), zod.z.record(zod.z.string(), ClusterAddonStatusEntrySchema), { auth: "admin" }), method(zod.z.object({ nodeId: zod.z.string() }), zod.z.array(NodeAddonEntrySchema).readonly(), { auth: "admin" }), method(zod.z.object({
5580
+ }), method(zod.z.void(), zod.z.record(zod.z.string(), ClusterAddonStatusEntrySchema), { auth: "admin" }), method(zod.z.object({ windowSeconds: zod.z.number().int().positive().max(300).default(60) }), zod.z.array(zod.z.object({
5581
+ callerAddonId: zod.z.string(),
5582
+ providerAddonId: zod.z.string(),
5583
+ capName: zod.z.string(),
5584
+ callsPerMin: zod.z.number(),
5585
+ lastCallAtMs: zod.z.number()
5586
+ })).readonly(), { auth: "admin" }), method(zod.z.object({ nodeId: zod.z.string() }), zod.z.array(NodeAddonEntrySchema).readonly(), { auth: "admin" }), method(zod.z.object({
5276
5587
  nodeId: zod.z.string(),
5277
5588
  level: zod.z.string()
5278
5589
  }), SuccessSchema, {
@@ -7510,6 +7821,16 @@ var StorageManager = class {
7510
7821
  }
7511
7822
  };
7512
7823
  //#endregion
7824
+ //#region src/auth/scope-matcher.ts
7825
+ /**
7826
+ * True if the scope set grants `access` on device-scoped capabilities.
7827
+ * A `category:device` grant covers every device cap (the broad grant).
7828
+ * Mirrors the OR-semantics of the existing token scope matcher.
7829
+ */
7830
+ function scopesAllowDeviceCap(scopes, access) {
7831
+ return scopes.some((s) => s.type === "category" && s.target === "device" && s.access.includes(access));
7832
+ }
7833
+ //#endregion
7513
7834
  //#region src/notification/notification-service.ts
7514
7835
  /**
7515
7836
  * Central notification service that routes notifications to configured outputs.
@@ -8335,5 +8656,6 @@ exports.installPythonPackages = installPythonPackages;
8335
8656
  exports.installPythonRequirements = installPythonRequirements;
8336
8657
  exports.isModelDownloaded = isModelDownloaded;
8337
8658
  exports.loadTlsCert = loadTlsCert;
8659
+ exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
8338
8660
 
8339
8661
  //# sourceMappingURL=index.js.map