@camstack/addon-post-analysis 0.1.14 → 0.1.15
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.
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/enrichment-engine/index.js +75 -7
- package/dist/enrichment-engine/index.js.map +1 -1
- package/dist/enrichment-engine/index.mjs +75 -7
- package/dist/enrichment-engine/index.mjs.map +1 -1
- package/dist/{index-tm6O4bWa.mjs → index-CGAj-pkn.mjs} +531 -97
- package/dist/index-CGAj-pkn.mjs.map +1 -0
- package/dist/{index-DNpNyDJi.js → index-Dbx13pc7.js} +531 -97
- package/dist/index-Dbx13pc7.js.map +1 -0
- package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/LiveStatsTab.d.ts +5 -0
- package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/index.d.ts +2 -0
- package/dist/pipeline-analytics/@mf-types.zip +0 -0
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-d8PmLbO2.mjs +19 -0
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BcWYbuKp.mjs +18 -0
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-DuO9h7li.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-D-USVuHq.mjs} +4 -2
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-CmqNjq44.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-qQCPW8pT.mjs} +1 -1
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CA8cCIEl.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-Bv9bYz9E.mjs} +1 -1
- package/dist/pipeline-analytics/_stub.js +497 -431
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-C7e1vVcD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DErNFTYO.mjs} +6 -6
- package/dist/pipeline-analytics/{client-DdXDZxzK.mjs → client-DHmQcIWy.mjs} +2990 -3217
- package/dist/pipeline-analytics/{hostInit-TFbPssJX.mjs → hostInit-DmzGJewr.mjs} +12 -12
- package/dist/pipeline-analytics/{index-DHiJ7A5x.mjs → index-BA65ZJOW.mjs} +1 -1
- package/dist/pipeline-analytics/{index-BP0-1QYT.mjs → index-BCEx31Mh.mjs} +3808 -3100
- package/dist/pipeline-analytics/{index-kIgjN-uq.mjs → index-CHnXxMRA.mjs} +1 -1
- package/dist/pipeline-analytics/index-CWkKuNLr.mjs +232 -0
- package/dist/pipeline-analytics/{index-B4OKsa9p.mjs → index-Crs1D0Uu.mjs} +1 -1
- package/dist/pipeline-analytics/{index-k0CA0h_r.mjs → index-DicaGC31.mjs} +1 -1
- package/dist/pipeline-analytics/index-gbflFMEY.mjs +36403 -0
- package/dist/pipeline-analytics/{index-DyYvUfc7.mjs → index-gpelkpEE.mjs} +1 -1
- package/dist/pipeline-analytics/index.js +73 -22
- package/dist/pipeline-analytics/index.js.map +1 -1
- package/dist/pipeline-analytics/index.mjs +73 -22
- package/dist/pipeline-analytics/index.mjs.map +1 -1
- package/dist/pipeline-analytics/{jsx-runtime-4ro1c69i.mjs → jsx-runtime-Wcfyyyt4.mjs} +1 -1
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/dist/recording/index.js +2 -2
- package/dist/recording/index.mjs +2 -2
- package/dist/{recording-coordinator-BVFZsuQg.mjs → recording-coordinator-BjWd7HjD.mjs} +2 -2
- package/dist/{recording-coordinator-BVFZsuQg.mjs.map → recording-coordinator-BjWd7HjD.mjs.map} +1 -1
- package/dist/{recording-coordinator-CL3NPb1p.js → recording-coordinator-b-7Ast8s.js} +2 -2
- package/dist/{recording-coordinator-CL3NPb1p.js.map → recording-coordinator-b-7Ast8s.js.map} +1 -1
- package/package.json +5 -1
- package/dist/index-DNpNyDJi.js.map +0 -1
- package/dist/index-tm6O4bWa.mjs.map +0 -1
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-CpCK52pE.mjs +0 -19
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-DEj77u_A.mjs +0 -15
- package/dist/pipeline-analytics/index-BDPtaPA2.mjs +0 -20855
|
@@ -5068,6 +5068,7 @@ const WELL_KNOWN_TABS = [
|
|
|
5068
5068
|
{ id: "osd", label: "OSD", icon: "type", order: 18 },
|
|
5069
5069
|
{ id: "stream-broker", label: "Stream Broker", icon: "radio", order: 20 },
|
|
5070
5070
|
{ id: "streaming", label: "Streaming", icon: "video", order: 35 },
|
|
5071
|
+
{ id: "ptz", label: "PTZ", icon: "move", order: 40 },
|
|
5071
5072
|
{ id: "pipeline", label: "Detection Pipeline", icon: "cpu", order: 39 },
|
|
5072
5073
|
{ id: "zones", label: "Detection", icon: "shapes", order: 38 },
|
|
5073
5074
|
{ id: "live-stats", label: "Live Stats", icon: "activity", order: 39 },
|
|
@@ -5135,6 +5136,9 @@ function hydrateField(field, values) {
|
|
|
5135
5136
|
return { ...field, value: items };
|
|
5136
5137
|
}
|
|
5137
5138
|
const rawValue = storedValue !== void 0 ? storedValue : defaultValue !== void 0 ? defaultValue : null;
|
|
5139
|
+
if (field.type === "password") {
|
|
5140
|
+
return { ...field, value: "" };
|
|
5141
|
+
}
|
|
5138
5142
|
const value = field.type === "textarea" && field.isJson && rawValue !== null && typeof rawValue === "object" ? JSON.stringify(rawValue, null, 2) : rawValue;
|
|
5139
5143
|
const hydrated = { ...field, value };
|
|
5140
5144
|
return hydrated;
|
|
@@ -5221,7 +5225,19 @@ const DecoderSessionConfigSchema = object({
|
|
|
5221
5225
|
* on every line so `grep tag=broker:5/high` filters one camera
|
|
5222
5226
|
* profile cleanly.
|
|
5223
5227
|
*/
|
|
5224
|
-
tag: string().optional()
|
|
5228
|
+
tag: string().optional(),
|
|
5229
|
+
/**
|
|
5230
|
+
* Where the session delivers decoded frames (Phase 5 / D9):
|
|
5231
|
+
*
|
|
5232
|
+
* - `'callback'` (default) — the legacy pixel path: decoded frames are
|
|
5233
|
+
* buffered as `DecodedFrame`s and drained via `pullFrames`.
|
|
5234
|
+
* - `'shm'` — the shared-memory frame plane: decoded frames are written
|
|
5235
|
+
* into an OS shared-memory ring and drained as zero-pixel
|
|
5236
|
+
* `FrameHandle`s via `pullHandles`. A session is one mode or the
|
|
5237
|
+
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
5238
|
+
* `pullHandles` returns nothing for a `'callback'` session.
|
|
5239
|
+
*/
|
|
5240
|
+
frameSink: _enum(["callback", "shm"]).default("callback")
|
|
5225
5241
|
});
|
|
5226
5242
|
function errMsg(err) {
|
|
5227
5243
|
if (err instanceof Error) return err.message;
|
|
@@ -5961,6 +5977,53 @@ const DecodedFrameSchema = object({
|
|
|
5961
5977
|
format: _enum(["jpeg", "rgb", "bgr", "yuv420", "gray"]),
|
|
5962
5978
|
timestamp: number()
|
|
5963
5979
|
});
|
|
5980
|
+
const FrameHandleSchema = object({
|
|
5981
|
+
shmId: string(),
|
|
5982
|
+
slot: number().int().nonnegative(),
|
|
5983
|
+
seq: number().int().nonnegative(),
|
|
5984
|
+
width: number().int().positive(),
|
|
5985
|
+
height: number().int().positive(),
|
|
5986
|
+
format: _enum(["jpeg", "rgb", "bgr", "yuv420", "gray"]),
|
|
5987
|
+
pts: number(),
|
|
5988
|
+
byteLength: number().int().nonnegative(),
|
|
5989
|
+
nodeId: string(),
|
|
5990
|
+
slotCount: number().int().positive()
|
|
5991
|
+
});
|
|
5992
|
+
const FrameHandleFormatSchema = _enum(["rgb", "bgr", "yuv420", "gray"]);
|
|
5993
|
+
const SubscribeFramesInputSchema = object({
|
|
5994
|
+
brokerId: string(),
|
|
5995
|
+
format: FrameHandleFormatSchema,
|
|
5996
|
+
/**
|
|
5997
|
+
* Optional reader-side cadence hint in frames per second. The broker does
|
|
5998
|
+
* NOT throttle — latest-wins ring reads drop frames implicitly for a slow
|
|
5999
|
+
* consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
|
|
6000
|
+
* the consumer can pace its own `pullFrameHandles` polling.
|
|
6001
|
+
*/
|
|
6002
|
+
maxFps: number().positive().optional(),
|
|
6003
|
+
/** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
|
|
6004
|
+
tag: string().optional()
|
|
6005
|
+
});
|
|
6006
|
+
const SubscribeFramesResultSchema = object({
|
|
6007
|
+
/** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
|
|
6008
|
+
subscriptionId: string(),
|
|
6009
|
+
/** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
|
|
6010
|
+
maxFps: number().nonnegative()
|
|
6011
|
+
});
|
|
6012
|
+
const DecodedAudioChunkSchema = object({
|
|
6013
|
+
data: _instanceof(Uint8Array),
|
|
6014
|
+
sampleRate: number().int().positive(),
|
|
6015
|
+
channels: number().int().positive(),
|
|
6016
|
+
timestamp: number()
|
|
6017
|
+
});
|
|
6018
|
+
const SubscribeAudioChunksInputSchema = object({
|
|
6019
|
+
brokerId: string(),
|
|
6020
|
+
/** Short caller-identity tag (`audio-analyzer`, …) for `listClients`. */
|
|
6021
|
+
tag: string().optional()
|
|
6022
|
+
});
|
|
6023
|
+
const SubscribeAudioChunksResultSchema = object({
|
|
6024
|
+
/** Opaque id passed to `pullAudioChunks` / `unsubscribeAudioChunks`. */
|
|
6025
|
+
subscriptionId: string()
|
|
6026
|
+
});
|
|
5964
6027
|
const BrokerStatusSchema$1 = _enum(["idle", "connecting", "streaming", "error", "stopped"]);
|
|
5965
6028
|
const BrokerStatsSchema = object({
|
|
5966
6029
|
status: BrokerStatusSchema$1,
|
|
@@ -6182,9 +6245,76 @@ const RtpSourceSchema = object({
|
|
|
6182
6245
|
object({ released: boolean(), refcount: number().int().nonnegative() }),
|
|
6183
6246
|
{ kind: "mutation", auth: "admin" }
|
|
6184
6247
|
),
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6248
|
+
/**
|
|
6249
|
+
* ── Decoded audio-chunk plane (Phase 5 / D9) ──────────────────────
|
|
6250
|
+
*
|
|
6251
|
+
* The serialisable replacement for the live-object `IStreamBroker.
|
|
6252
|
+
* onDecodedAudioChunk` callback path. Unlike the video frame plane,
|
|
6253
|
+
* audio chunks are tiny (a ~500ms PCM window is a few KB) so they ship
|
|
6254
|
+
* their bytes INLINE over tRPC — no shared-memory ring. A consumer:
|
|
6255
|
+
*
|
|
6256
|
+
* 1. `subscribeAudioChunks({ brokerId, tag })` — the broker registers
|
|
6257
|
+
* a per-subscription bounded FIFO queue and returns a
|
|
6258
|
+
* `subscriptionId`.
|
|
6259
|
+
* 2. polls `pullAudioChunks({ subscriptionId, maxCount })` — drains
|
|
6260
|
+
* `DecodedAudioChunk[]` in arrival order (FIFO, no latest-wins
|
|
6261
|
+
* drop: an audio gap is audible / breaks an analysis window). The
|
|
6262
|
+
* queue is generously sized; it only drops its oldest chunk if a
|
|
6263
|
+
* truly stalled consumer lets it overflow.
|
|
6264
|
+
* 3. `unsubscribeAudioChunks({ subscriptionId })` on teardown.
|
|
6265
|
+
*/
|
|
6266
|
+
subscribeAudioChunks: method(
|
|
6267
|
+
SubscribeAudioChunksInputSchema,
|
|
6268
|
+
SubscribeAudioChunksResultSchema,
|
|
6269
|
+
{ kind: "mutation" }
|
|
6270
|
+
),
|
|
6271
|
+
pullAudioChunks: method(
|
|
6272
|
+
object({
|
|
6273
|
+
subscriptionId: string(),
|
|
6274
|
+
maxCount: number().int().positive().default(8)
|
|
6275
|
+
}),
|
|
6276
|
+
array(DecodedAudioChunkSchema).readonly()
|
|
6277
|
+
),
|
|
6278
|
+
unsubscribeAudioChunks: method(
|
|
6279
|
+
object({ subscriptionId: string() }),
|
|
6280
|
+
object({ released: boolean() }),
|
|
6281
|
+
{ kind: "mutation" }
|
|
6282
|
+
),
|
|
6283
|
+
/**
|
|
6284
|
+
* ── Shared-memory frame plane (Phase 5 / D9) ──────────────────────
|
|
6285
|
+
*
|
|
6286
|
+
* The handle-based replacement for the live-object `IStreamBroker.
|
|
6287
|
+
* onDecodedFrame` callback path. A consumer:
|
|
6288
|
+
*
|
|
6289
|
+
* 1. `subscribeFrames({ brokerId, format })` — the broker spins up
|
|
6290
|
+
* (or reuses) a `frameSink: 'shm'` decoder session producing that
|
|
6291
|
+
* `format` and returns a `subscriptionId`.
|
|
6292
|
+
* 2. polls `pullFrameHandles({ subscriptionId, maxCount })` — drains
|
|
6293
|
+
* zero-pixel `FrameHandle[]`; each handle is fed to a
|
|
6294
|
+
* `FrameRingReader` that opens the named shm segment and reads the
|
|
6295
|
+
* pixels back zero-copy.
|
|
6296
|
+
* 3. `unsubscribeFrames({ subscriptionId })` on teardown.
|
|
6297
|
+
*
|
|
6298
|
+
* The broker keeps one shm ring per `(brokerId, format)` actually
|
|
6299
|
+
* requested — no broker-side `sharp` conversion. fps throttling is
|
|
6300
|
+
* implicit (latest-wins ring reads drop frames for a slow consumer).
|
|
6301
|
+
*/
|
|
6302
|
+
subscribeFrames: method(
|
|
6303
|
+
SubscribeFramesInputSchema,
|
|
6304
|
+
SubscribeFramesResultSchema,
|
|
6305
|
+
{ kind: "mutation" }
|
|
6306
|
+
),
|
|
6307
|
+
pullFrameHandles: method(
|
|
6308
|
+
object({
|
|
6309
|
+
subscriptionId: string(),
|
|
6310
|
+
maxCount: number().int().positive().default(4)
|
|
6311
|
+
}),
|
|
6312
|
+
array(FrameHandleSchema).readonly()
|
|
6313
|
+
),
|
|
6314
|
+
unsubscribeFrames: method(
|
|
6315
|
+
object({ subscriptionId: string() }),
|
|
6316
|
+
object({ released: boolean() }),
|
|
6317
|
+
{ kind: "mutation" }
|
|
6188
6318
|
),
|
|
6189
6319
|
setPreBufferDuration: method(
|
|
6190
6320
|
object({ brokerId: string(), seconds: number().min(0).max(30) }),
|
|
@@ -7262,6 +7392,34 @@ MotionTriggerStatusSchema.extend({
|
|
|
7262
7392
|
}) }
|
|
7263
7393
|
}
|
|
7264
7394
|
});
|
|
7395
|
+
object({
|
|
7396
|
+
enabled: boolean(),
|
|
7397
|
+
sensitivity: number(),
|
|
7398
|
+
/** Row-major active-cell grid. Length = gridWidth*gridHeight (see getOptions). */
|
|
7399
|
+
cells: array(boolean()),
|
|
7400
|
+
lastFetchedAt: number()
|
|
7401
|
+
});
|
|
7402
|
+
const MotionZoneOptionsSchema = object({
|
|
7403
|
+
gridWidth: number(),
|
|
7404
|
+
gridHeight: number(),
|
|
7405
|
+
sensitivity: object({ min: number(), max: number(), step: number() })
|
|
7406
|
+
});
|
|
7407
|
+
const MotionZonePatchSchema = object({
|
|
7408
|
+
enabled: boolean().optional(),
|
|
7409
|
+
sensitivity: number().optional(),
|
|
7410
|
+
cells: array(boolean()).optional()
|
|
7411
|
+
});
|
|
7412
|
+
({
|
|
7413
|
+
deviceTypes: [DeviceType.Camera],
|
|
7414
|
+
methods: {
|
|
7415
|
+
getOptions: method(object({ deviceId: number() }), MotionZoneOptionsSchema),
|
|
7416
|
+
setZone: method(
|
|
7417
|
+
object({ deviceId: number(), patch: MotionZonePatchSchema }),
|
|
7418
|
+
_void(),
|
|
7419
|
+
{ kind: "mutation", auth: "admin" }
|
|
7420
|
+
)
|
|
7421
|
+
}
|
|
7422
|
+
});
|
|
7265
7423
|
const AutotrackTargetTypeSchema = string().describe("Vendor target string (people/vehicle/pet); empty = camera default");
|
|
7266
7424
|
const PtzAutotrackSettingsSchema = object({
|
|
7267
7425
|
targetType: AutotrackTargetTypeSchema,
|
|
@@ -7350,6 +7508,100 @@ PtzAutotrackStatusSchema.extend({
|
|
|
7350
7508
|
}) }
|
|
7351
7509
|
}
|
|
7352
7510
|
});
|
|
7511
|
+
const StreamProfileSchema = _enum(["main", "sub", "ext"]);
|
|
7512
|
+
const StreamProfileConfigSchema = object({
|
|
7513
|
+
width: number(),
|
|
7514
|
+
height: number(),
|
|
7515
|
+
codec: _enum(["h264", "h265"]),
|
|
7516
|
+
framerate: number(),
|
|
7517
|
+
bitrate: number(),
|
|
7518
|
+
// kbps
|
|
7519
|
+
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
7520
|
+
encoderProfile: _enum(["high", "main", "baseline"]).optional(),
|
|
7521
|
+
gop: number().optional(),
|
|
7522
|
+
audio: boolean().optional()
|
|
7523
|
+
});
|
|
7524
|
+
object({
|
|
7525
|
+
/** Per-profile current config. A profile absent = the camera doesn't have it. */
|
|
7526
|
+
main: StreamProfileConfigSchema.optional(),
|
|
7527
|
+
sub: StreamProfileConfigSchema.optional(),
|
|
7528
|
+
ext: StreamProfileConfigSchema.optional(),
|
|
7529
|
+
lastFetchedAt: number()
|
|
7530
|
+
});
|
|
7531
|
+
const StreamProfileOptionsSchema = object({
|
|
7532
|
+
resolutions: array(object({ width: number(), height: number() })),
|
|
7533
|
+
codecs: array(_enum(["h264", "h265"])),
|
|
7534
|
+
framerates: array(number()),
|
|
7535
|
+
/** Allowed bitrate values (kbps). Empty if the camera takes a free range. */
|
|
7536
|
+
bitrates: array(number()),
|
|
7537
|
+
/** Optional [min,max] kbps when the camera accepts a continuous range. */
|
|
7538
|
+
bitrateRange: tuple([number(), number()]).optional(),
|
|
7539
|
+
supportsBitrateMode: boolean(),
|
|
7540
|
+
supportsEncoderProfile: boolean(),
|
|
7541
|
+
supportsGop: boolean(),
|
|
7542
|
+
/** Allowed GOP / keyframe-interval range, in seconds — drives the
|
|
7543
|
+
* I-frame-interval selector. Absent when the camera advertises GOP
|
|
7544
|
+
* support but no concrete range (callers then fall back to a free
|
|
7545
|
+
* numeric input). `{ min, max, step }` per the getOptions convention. */
|
|
7546
|
+
gop: object({ min: number(), max: number(), step: number() }).optional()
|
|
7547
|
+
});
|
|
7548
|
+
const StreamParamsOptionsSchema = object({
|
|
7549
|
+
main: StreamProfileOptionsSchema.optional(),
|
|
7550
|
+
sub: StreamProfileOptionsSchema.optional(),
|
|
7551
|
+
ext: StreamProfileOptionsSchema.optional()
|
|
7552
|
+
});
|
|
7553
|
+
const StreamProfilePatchSchema = object({
|
|
7554
|
+
width: number().optional(),
|
|
7555
|
+
height: number().optional(),
|
|
7556
|
+
codec: _enum(["h264", "h265"]).optional(),
|
|
7557
|
+
framerate: number().optional(),
|
|
7558
|
+
bitrate: number().optional(),
|
|
7559
|
+
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
7560
|
+
encoderProfile: _enum(["high", "main", "baseline"]).optional(),
|
|
7561
|
+
gop: number().optional(),
|
|
7562
|
+
audio: boolean().optional()
|
|
7563
|
+
});
|
|
7564
|
+
({
|
|
7565
|
+
deviceTypes: [DeviceType.Camera],
|
|
7566
|
+
methods: {
|
|
7567
|
+
getOptions: method(
|
|
7568
|
+
object({ deviceId: number() }),
|
|
7569
|
+
StreamParamsOptionsSchema
|
|
7570
|
+
),
|
|
7571
|
+
setProfile: method(
|
|
7572
|
+
object({
|
|
7573
|
+
deviceId: number(),
|
|
7574
|
+
profile: StreamProfileSchema,
|
|
7575
|
+
patch: StreamProfilePatchSchema
|
|
7576
|
+
}),
|
|
7577
|
+
_void(),
|
|
7578
|
+
{ kind: "mutation", auth: "admin" }
|
|
7579
|
+
),
|
|
7580
|
+
/**
|
|
7581
|
+
* Build the `ConfigUISchema` (admin-ui `ConfigFormBuilder` input
|
|
7582
|
+
* shape) for this camera's stream-encoder settings — one section per
|
|
7583
|
+
* profile (main / sub / ext) with the resolution / codec / framerate
|
|
7584
|
+
* / bitrate / bitrate-mode / encoder-profile / GOP controls the
|
|
7585
|
+
* firmware actually exposes.
|
|
7586
|
+
*
|
|
7587
|
+
* Driven by `getOptions` (camera-probed availability) + `getStatus`
|
|
7588
|
+
* (current per-profile config); each field's `default` is seeded
|
|
7589
|
+
* from the live config so the form renders the camera state in one
|
|
7590
|
+
* pass. Returns `null` when the camera exposes no configurable
|
|
7591
|
+
* stream property — the renderer then shows the unsupported message.
|
|
7592
|
+
*
|
|
7593
|
+
* Output is `z.unknown().nullable()` — the same convention every
|
|
7594
|
+
* other `ConfigUISchema`-returning cap method uses (`device-ops`,
|
|
7595
|
+
* `device-manager`); `ConfigUISchema` is a TS-only type with no
|
|
7596
|
+
* companion Zod schema, and a concrete object would collapse
|
|
7597
|
+
* unrelated AppRouter branches to `unknown` during codegen.
|
|
7598
|
+
*/
|
|
7599
|
+
getConfigSchema: method(
|
|
7600
|
+
object({ deviceId: number() }),
|
|
7601
|
+
unknown().nullable()
|
|
7602
|
+
)
|
|
7603
|
+
}
|
|
7604
|
+
});
|
|
7353
7605
|
object({
|
|
7354
7606
|
on: boolean(),
|
|
7355
7607
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
@@ -8298,6 +8550,83 @@ const VersionOutputSchema = object({ version: string() });
|
|
|
8298
8550
|
getVersion: method(_void(), VersionOutputSchema)
|
|
8299
8551
|
}
|
|
8300
8552
|
});
|
|
8553
|
+
const MethodAccessSchema = _enum(["view", "create", "delete"]);
|
|
8554
|
+
const AllowedProviderSchema = union([literal("*"), array(string())]);
|
|
8555
|
+
const AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
|
|
8556
|
+
const CapScopeSchema = _enum(["device", "system"]);
|
|
8557
|
+
const TokenScopeSchema = discriminatedUnion("type", [
|
|
8558
|
+
object({
|
|
8559
|
+
type: literal("category"),
|
|
8560
|
+
target: CapScopeSchema,
|
|
8561
|
+
access: array(MethodAccessSchema).min(1)
|
|
8562
|
+
}),
|
|
8563
|
+
object({
|
|
8564
|
+
type: literal("capability"),
|
|
8565
|
+
target: string(),
|
|
8566
|
+
access: array(MethodAccessSchema).min(1)
|
|
8567
|
+
}),
|
|
8568
|
+
object({
|
|
8569
|
+
type: literal("addon"),
|
|
8570
|
+
target: string(),
|
|
8571
|
+
access: array(MethodAccessSchema).min(1)
|
|
8572
|
+
}),
|
|
8573
|
+
object({
|
|
8574
|
+
type: literal("device"),
|
|
8575
|
+
/**
|
|
8576
|
+
* One or more deviceIds (serialised as strings for wire-format
|
|
8577
|
+
* consistency with the rest of the union). Matcher accepts if
|
|
8578
|
+
* `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
|
|
8579
|
+
* of one scope-per-device when granting access to a set of cameras.
|
|
8580
|
+
*/
|
|
8581
|
+
targets: array(string()).min(1),
|
|
8582
|
+
access: array(MethodAccessSchema).min(1)
|
|
8583
|
+
})
|
|
8584
|
+
]);
|
|
8585
|
+
object({
|
|
8586
|
+
id: string(),
|
|
8587
|
+
username: string(),
|
|
8588
|
+
passwordHash: string(),
|
|
8589
|
+
/**
|
|
8590
|
+
* Admin bypass. When true, the middleware skips the scope-access
|
|
8591
|
+
* check entirely. There is no other axis of privilege; the legacy
|
|
8592
|
+
* role enum collapsed onto this boolean in v2.
|
|
8593
|
+
*/
|
|
8594
|
+
isAdmin: boolean().default(false),
|
|
8595
|
+
allowedProviders: AllowedProviderSchema,
|
|
8596
|
+
allowedDevices: AllowedDevicesSchema,
|
|
8597
|
+
/**
|
|
8598
|
+
* Scopes granted to this user. Admins bypass; their `scopes` is
|
|
8599
|
+
* ignored. Non-admins without scopes are locked out of every
|
|
8600
|
+
* protected call.
|
|
8601
|
+
*/
|
|
8602
|
+
scopes: array(TokenScopeSchema).default([]),
|
|
8603
|
+
createdAt: number(),
|
|
8604
|
+
updatedAt: number()
|
|
8605
|
+
});
|
|
8606
|
+
object({
|
|
8607
|
+
id: string(),
|
|
8608
|
+
label: string(),
|
|
8609
|
+
isAdmin: boolean().default(false),
|
|
8610
|
+
allowedProviders: AllowedProviderSchema,
|
|
8611
|
+
allowedDevices: AllowedDevicesSchema,
|
|
8612
|
+
tokenHash: string(),
|
|
8613
|
+
tokenPrefix: string(),
|
|
8614
|
+
createdAt: number(),
|
|
8615
|
+
lastUsedAt: number().optional()
|
|
8616
|
+
});
|
|
8617
|
+
object({
|
|
8618
|
+
id: string(),
|
|
8619
|
+
userId: string(),
|
|
8620
|
+
name: string(),
|
|
8621
|
+
tokenHash: string(),
|
|
8622
|
+
tokenPrefix: string(),
|
|
8623
|
+
scopes: array(TokenScopeSchema),
|
|
8624
|
+
// SQLite/JSON storage round-trips undefined → null. Use `nullish` so the
|
|
8625
|
+
// schema accepts both `null` (read from disk) and `undefined` (in-memory).
|
|
8626
|
+
expiresAt: number().nullish(),
|
|
8627
|
+
lastUsedAt: number().nullish(),
|
|
8628
|
+
createdAt: number()
|
|
8629
|
+
});
|
|
8301
8630
|
const SsoBridgeClaimsSchema = object({
|
|
8302
8631
|
userId: string(),
|
|
8303
8632
|
username: string(),
|
|
@@ -8313,7 +8642,18 @@ const SsoBridgeClaimsSchema = object({
|
|
|
8313
8642
|
* JWT WITHOUT verifying the signature — the hub re-verifies on every
|
|
8314
8643
|
* inbound call so trust still rests with the signing hub.
|
|
8315
8644
|
*/
|
|
8316
|
-
hubUrl: string().optional()
|
|
8645
|
+
hubUrl: string().optional(),
|
|
8646
|
+
/** Permission scopes baked into the token. Set by the OAuth
|
|
8647
|
+
* account-linking grant; absent on ordinary SSO-login tokens. */
|
|
8648
|
+
scopes: array(TokenScopeSchema).optional(),
|
|
8649
|
+
/** OAuth authorization-code binding — set only on `oauth-code` tokens. */
|
|
8650
|
+
redirectUri: string().optional(),
|
|
8651
|
+
integrationId: string().optional(),
|
|
8652
|
+
/** JWT ID — unique per issued code; consumed-set enforces single-use. */
|
|
8653
|
+
jti: string().optional(),
|
|
8654
|
+
/** OAuth session registry id — set on `oauth-access`/`oauth-refresh`
|
|
8655
|
+
* tokens so the verify path can check the session is not revoked. */
|
|
8656
|
+
sessionId: string().optional()
|
|
8317
8657
|
});
|
|
8318
8658
|
({
|
|
8319
8659
|
methods: {
|
|
@@ -8330,6 +8670,23 @@ const SsoBridgeClaimsSchema = object({
|
|
|
8330
8670
|
)
|
|
8331
8671
|
}
|
|
8332
8672
|
});
|
|
8673
|
+
const OauthIntegrationDescriptorSchema = object({
|
|
8674
|
+
/** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
|
|
8675
|
+
integrationId: string(),
|
|
8676
|
+
/** Human label rendered on the consent page. */
|
|
8677
|
+
displayName: string(),
|
|
8678
|
+
/** Scopes baked into every token issued for this integration. */
|
|
8679
|
+
requestedScopes: array(TokenScopeSchema),
|
|
8680
|
+
/** Allowed redirect_uri prefixes. /api/oauth2/authorize rejects any
|
|
8681
|
+
* redirect_uri that does not start with one of these. Required —
|
|
8682
|
+
* an empty list means the integration can never complete linking. */
|
|
8683
|
+
allowedRedirectPrefixes: array(string()).min(1)
|
|
8684
|
+
});
|
|
8685
|
+
({
|
|
8686
|
+
methods: {
|
|
8687
|
+
getDescriptor: method(_void(), OauthIntegrationDescriptorSchema)
|
|
8688
|
+
}
|
|
8689
|
+
});
|
|
8333
8690
|
const PasskeySummarySchema = object({
|
|
8334
8691
|
credentialId: string(),
|
|
8335
8692
|
label: string(),
|
|
@@ -8610,21 +8967,30 @@ const AddonPageDeclarationSchema = object({
|
|
|
8610
8967
|
});
|
|
8611
8968
|
const WidgetHostEnum = _enum(["device-tab", "dashboard", "integration-detail"]);
|
|
8612
8969
|
const WidgetSizeEnum = _enum(["xs", "sm", "md", "lg", "xl"]);
|
|
8970
|
+
const WidgetRemoteSchema = object({
|
|
8971
|
+
remoteName: string(),
|
|
8972
|
+
exposedModule: string(),
|
|
8973
|
+
componentKey: string().optional()
|
|
8974
|
+
});
|
|
8613
8975
|
const WidgetMetadataSchema = object({
|
|
8614
|
-
|
|
8615
|
-
|
|
8976
|
+
// ── UiContribution core (kind:'remote') ──────────────────────────
|
|
8977
|
+
/** Primary host tab — `'dashboard'`, `'device-tab'`, or a device-detail tab id. */
|
|
8978
|
+
tab: string(),
|
|
8979
|
+
/** Optional sub-tab within `tab`. */
|
|
8980
|
+
subTab: string().optional(),
|
|
8616
8981
|
/** Operator-facing label. */
|
|
8617
8982
|
label: string(),
|
|
8983
|
+
/** Ordering within `(tab, subTab)`, ascending. */
|
|
8984
|
+
order: number().optional(),
|
|
8985
|
+
/** Always `'remote'` — a widget is a Module Federation remote. */
|
|
8986
|
+
kind: literal("remote"),
|
|
8987
|
+
/** MF remote descriptor. */
|
|
8988
|
+
remote: WidgetRemoteSchema,
|
|
8989
|
+
// ── Widget-only metadata ─────────────────────────────────────────
|
|
8990
|
+
/** Stable id within the addon — kebab-case. Equals `remote.componentKey`. */
|
|
8991
|
+
stableId: string(),
|
|
8618
8992
|
description: string().optional(),
|
|
8619
8993
|
icon: string().optional(),
|
|
8620
|
-
/**
|
|
8621
|
-
* Module Federation remote name — must match the `name` field on the
|
|
8622
|
-
* widget addon's `federation()` plugin config. Used by the host's
|
|
8623
|
-
* `<WidgetRegistryProvider>` to call `loadRemote('<remoteName>/widgets')`.
|
|
8624
|
-
* Conventionally `addon_<addonid>_widgets` (snake_case; MF names
|
|
8625
|
-
* cannot contain hyphens).
|
|
8626
|
-
*/
|
|
8627
|
-
remoteName: string(),
|
|
8628
8994
|
/**
|
|
8629
8995
|
* Bundle filename inside the addon's `dist/` dir served at
|
|
8630
8996
|
* `/api/addon-widgets/<addonId>/<bundle>`. With Module Federation
|
|
@@ -8633,9 +8999,9 @@ const WidgetMetadataSchema = object({
|
|
|
8633
8999
|
* cache-buster URL without a separate filesystem stat.
|
|
8634
9000
|
*/
|
|
8635
9001
|
bundle: string(),
|
|
8636
|
-
/**
|
|
9002
|
+
/** Every host the widget supports. The picker filters on this set. */
|
|
8637
9003
|
hosts: array(WidgetHostEnum).readonly(),
|
|
8638
|
-
/** Required props the host must supply. Validated at
|
|
9004
|
+
/** Required props the host must supply. Validated at `<WidgetSlot>` mount. */
|
|
8639
9005
|
requires: object({
|
|
8640
9006
|
deviceContext: boolean().default(false),
|
|
8641
9007
|
integrationContext: boolean().default(false)
|
|
@@ -8710,6 +9076,16 @@ const InvokeReplyEnvelopeSchema = object({
|
|
|
8710
9076
|
invoke: method(InvokeRequestSchema, InvokeReplyEnvelopeSchema, { kind: "mutation" })
|
|
8711
9077
|
}
|
|
8712
9078
|
});
|
|
9079
|
+
const ShmRingStatsSchema = object({
|
|
9080
|
+
sessionId: string(),
|
|
9081
|
+
slotCount: number().int(),
|
|
9082
|
+
slotByteLength: number().int(),
|
|
9083
|
+
segmentBytes: number().int(),
|
|
9084
|
+
budgetMb: number().int(),
|
|
9085
|
+
framesWritten: number().int(),
|
|
9086
|
+
getFrameHits: number().int(),
|
|
9087
|
+
getFrameMisses: number().int()
|
|
9088
|
+
});
|
|
8713
9089
|
({
|
|
8714
9090
|
methods: {
|
|
8715
9091
|
// ── Discovery ─────────────────────────────────────────────────
|
|
@@ -8737,10 +9113,27 @@ const InvokeReplyEnvelopeSchema = object({
|
|
|
8737
9113
|
url: string()
|
|
8738
9114
|
}), _void()),
|
|
8739
9115
|
// ── Output — polling-based frame retrieval ────────────────────
|
|
9116
|
+
// `pullFrames` drains the pixel `DecodedFrame[]` of a `frameSink:
|
|
9117
|
+
// 'callback'` session. `pullHandles` (Phase 5 / D9) drains the
|
|
9118
|
+
// zero-pixel `FrameHandle[]` of a `frameSink: 'shm'` session — the
|
|
9119
|
+
// broker hands each handle to a `FrameRingReader` that opens the
|
|
9120
|
+
// named segment and reads the pixels back zero-copy. A session is
|
|
9121
|
+
// one mode or the other; the unmatched method returns an empty
|
|
9122
|
+
// array.
|
|
8740
9123
|
pullFrames: method(object({
|
|
8741
9124
|
sessionId: string(),
|
|
8742
9125
|
maxCount: number().default(1)
|
|
8743
9126
|
}), array(DecodedFrameSchema)),
|
|
9127
|
+
pullHandles: method(object({
|
|
9128
|
+
sessionId: string(),
|
|
9129
|
+
maxCount: number().default(1)
|
|
9130
|
+
}), array(FrameHandleSchema)),
|
|
9131
|
+
// ── Frame fetch (Phase 5 / D9 downstream access) ──────────────
|
|
9132
|
+
// Read the pixels a FrameHandle refers to from this node's shm ring.
|
|
9133
|
+
// Returns null when the slot was already recycled (latest-wins).
|
|
9134
|
+
getFrame: method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()),
|
|
9135
|
+
// shm ring usage stats for a session.
|
|
9136
|
+
getShmStats: method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()),
|
|
8744
9137
|
// ── Control ───────────────────────────────────────────────────
|
|
8745
9138
|
updateConfig: method(object({
|
|
8746
9139
|
sessionId: string(),
|
|
@@ -9912,8 +10305,8 @@ const DevicePersistConfigPayloadSchema = object({
|
|
|
9912
10305
|
/**
|
|
9913
10306
|
* Return the addon ids that declared a wrapper provider for `capName`.
|
|
9914
10307
|
* Backs the device-bindings UI's wrapper-picker dropdown. Entries are
|
|
9915
|
-
* sourced from `CapabilityRegistry.wrapperProviders`, populated
|
|
9916
|
-
* `
|
|
10308
|
+
* sourced from `CapabilityRegistry.wrapperProviders`, populated when
|
|
10309
|
+
* the cap definition declares `kind: 'wrapper'`.
|
|
9917
10310
|
*/
|
|
9918
10311
|
listWrappersForCap: method(
|
|
9919
10312
|
object({ capName: string() }),
|
|
@@ -10724,6 +11117,8 @@ const pipelineAnalyticsCapability = {
|
|
|
10724
11117
|
name: "pipeline-analytics",
|
|
10725
11118
|
scope: "device",
|
|
10726
11119
|
mode: "singleton",
|
|
11120
|
+
kind: "wrapper",
|
|
11121
|
+
defaultActive: true,
|
|
10727
11122
|
deviceTypes: [DeviceType.Camera],
|
|
10728
11123
|
exposesDeviceSettings: true,
|
|
10729
11124
|
methods: {
|
|
@@ -11010,6 +11405,18 @@ const PtzMoveCommandSchema = object({
|
|
|
11010
11405
|
zoom: number().optional(),
|
|
11011
11406
|
speed: number().optional()
|
|
11012
11407
|
});
|
|
11408
|
+
PtzPositionSchema.extend({ autofocus: boolean() });
|
|
11409
|
+
const PtzOptionsSchema = object({
|
|
11410
|
+
hasPan: boolean(),
|
|
11411
|
+
hasTilt: boolean(),
|
|
11412
|
+
hasZoom: boolean(),
|
|
11413
|
+
supportsPresets: boolean(),
|
|
11414
|
+
/** Max number of named presets the camera supports, when known. */
|
|
11415
|
+
maxPresets: number().optional(),
|
|
11416
|
+
/** Whether the camera exposes a controllable autofocus toggle
|
|
11417
|
+
* (boolean `hasX` per the getOptions availability convention). */
|
|
11418
|
+
hasAutofocus: boolean()
|
|
11419
|
+
});
|
|
11013
11420
|
({
|
|
11014
11421
|
deviceTypes: [DeviceType.Camera],
|
|
11015
11422
|
methods: {
|
|
@@ -11037,6 +11444,20 @@ const PtzMoveCommandSchema = object({
|
|
|
11037
11444
|
_void(),
|
|
11038
11445
|
{ kind: "mutation" }
|
|
11039
11446
|
),
|
|
11447
|
+
savePreset: method(
|
|
11448
|
+
object({ deviceId: number(), presetId: string(), name: string() }),
|
|
11449
|
+
_void(),
|
|
11450
|
+
{ kind: "mutation", auth: "admin" }
|
|
11451
|
+
),
|
|
11452
|
+
deletePreset: method(
|
|
11453
|
+
object({ deviceId: number(), presetId: string() }),
|
|
11454
|
+
_void(),
|
|
11455
|
+
{ kind: "mutation", auth: "admin" }
|
|
11456
|
+
),
|
|
11457
|
+
getOptions: method(
|
|
11458
|
+
object({ deviceId: number() }),
|
|
11459
|
+
PtzOptionsSchema
|
|
11460
|
+
),
|
|
11040
11461
|
goHome: method(
|
|
11041
11462
|
object({ deviceId: number() }),
|
|
11042
11463
|
_void(),
|
|
@@ -11051,6 +11472,13 @@ const PtzMoveCommandSchema = object({
|
|
|
11051
11472
|
getPosition: method(
|
|
11052
11473
|
object({ deviceId: number() }),
|
|
11053
11474
|
PtzPositionSchema
|
|
11475
|
+
),
|
|
11476
|
+
/** Toggle the camera's autofocus. Only meaningful when
|
|
11477
|
+
* `getOptions().hasAutofocus` is true. */
|
|
11478
|
+
setAutofocus: method(
|
|
11479
|
+
object({ deviceId: number(), enabled: boolean() }),
|
|
11480
|
+
_void(),
|
|
11481
|
+
{ kind: "mutation" }
|
|
11054
11482
|
)
|
|
11055
11483
|
}
|
|
11056
11484
|
});
|
|
@@ -11986,83 +12414,6 @@ const MeshStatusSchema = object({
|
|
|
11986
12414
|
// tabs driven by this cap.
|
|
11987
12415
|
}
|
|
11988
12416
|
});
|
|
11989
|
-
const MethodAccessSchema = _enum(["view", "create", "delete"]);
|
|
11990
|
-
const AllowedProviderSchema = union([literal("*"), array(string())]);
|
|
11991
|
-
const AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
|
|
11992
|
-
const CapScopeSchema = _enum(["device", "system"]);
|
|
11993
|
-
const TokenScopeSchema = discriminatedUnion("type", [
|
|
11994
|
-
object({
|
|
11995
|
-
type: literal("category"),
|
|
11996
|
-
target: CapScopeSchema,
|
|
11997
|
-
access: array(MethodAccessSchema).min(1)
|
|
11998
|
-
}),
|
|
11999
|
-
object({
|
|
12000
|
-
type: literal("capability"),
|
|
12001
|
-
target: string(),
|
|
12002
|
-
access: array(MethodAccessSchema).min(1)
|
|
12003
|
-
}),
|
|
12004
|
-
object({
|
|
12005
|
-
type: literal("addon"),
|
|
12006
|
-
target: string(),
|
|
12007
|
-
access: array(MethodAccessSchema).min(1)
|
|
12008
|
-
}),
|
|
12009
|
-
object({
|
|
12010
|
-
type: literal("device"),
|
|
12011
|
-
/**
|
|
12012
|
-
* One or more deviceIds (serialised as strings for wire-format
|
|
12013
|
-
* consistency with the rest of the union). Matcher accepts if
|
|
12014
|
-
* `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
|
|
12015
|
-
* of one scope-per-device when granting access to a set of cameras.
|
|
12016
|
-
*/
|
|
12017
|
-
targets: array(string()).min(1),
|
|
12018
|
-
access: array(MethodAccessSchema).min(1)
|
|
12019
|
-
})
|
|
12020
|
-
]);
|
|
12021
|
-
object({
|
|
12022
|
-
id: string(),
|
|
12023
|
-
username: string(),
|
|
12024
|
-
passwordHash: string(),
|
|
12025
|
-
/**
|
|
12026
|
-
* Admin bypass. When true, the middleware skips the scope-access
|
|
12027
|
-
* check entirely. There is no other axis of privilege; the legacy
|
|
12028
|
-
* role enum collapsed onto this boolean in v2.
|
|
12029
|
-
*/
|
|
12030
|
-
isAdmin: boolean().default(false),
|
|
12031
|
-
allowedProviders: AllowedProviderSchema,
|
|
12032
|
-
allowedDevices: AllowedDevicesSchema,
|
|
12033
|
-
/**
|
|
12034
|
-
* Scopes granted to this user. Admins bypass; their `scopes` is
|
|
12035
|
-
* ignored. Non-admins without scopes are locked out of every
|
|
12036
|
-
* protected call.
|
|
12037
|
-
*/
|
|
12038
|
-
scopes: array(TokenScopeSchema).default([]),
|
|
12039
|
-
createdAt: number(),
|
|
12040
|
-
updatedAt: number()
|
|
12041
|
-
});
|
|
12042
|
-
object({
|
|
12043
|
-
id: string(),
|
|
12044
|
-
label: string(),
|
|
12045
|
-
isAdmin: boolean().default(false),
|
|
12046
|
-
allowedProviders: AllowedProviderSchema,
|
|
12047
|
-
allowedDevices: AllowedDevicesSchema,
|
|
12048
|
-
tokenHash: string(),
|
|
12049
|
-
tokenPrefix: string(),
|
|
12050
|
-
createdAt: number(),
|
|
12051
|
-
lastUsedAt: number().optional()
|
|
12052
|
-
});
|
|
12053
|
-
object({
|
|
12054
|
-
id: string(),
|
|
12055
|
-
userId: string(),
|
|
12056
|
-
name: string(),
|
|
12057
|
-
tokenHash: string(),
|
|
12058
|
-
tokenPrefix: string(),
|
|
12059
|
-
scopes: array(TokenScopeSchema),
|
|
12060
|
-
// SQLite/JSON storage round-trips undefined → null. Use `nullish` so the
|
|
12061
|
-
// schema accepts both `null` (read from disk) and `undefined` (in-memory).
|
|
12062
|
-
expiresAt: number().nullish(),
|
|
12063
|
-
lastUsedAt: number().nullish(),
|
|
12064
|
-
createdAt: number()
|
|
12065
|
-
});
|
|
12066
12417
|
const UserSummarySchema = object({
|
|
12067
12418
|
id: string(),
|
|
12068
12419
|
username: string(),
|
|
@@ -12135,6 +12486,16 @@ const CreateScopedTokenResultSchema = object({
|
|
|
12135
12486
|
token: string(),
|
|
12136
12487
|
record: ScopedTokenSummarySchema
|
|
12137
12488
|
});
|
|
12489
|
+
const OauthSessionSummarySchema = object({
|
|
12490
|
+
id: string(),
|
|
12491
|
+
userId: string(),
|
|
12492
|
+
username: string(),
|
|
12493
|
+
integrationId: string(),
|
|
12494
|
+
scopes: array(TokenScopeSchema),
|
|
12495
|
+
createdAt: number(),
|
|
12496
|
+
lastUsedAt: number(),
|
|
12497
|
+
revokedAt: number().nullable()
|
|
12498
|
+
});
|
|
12138
12499
|
const TotpSetupResultSchema = object({
|
|
12139
12500
|
secret: string(),
|
|
12140
12501
|
otpauthUrl: string()
|
|
@@ -12210,6 +12571,66 @@ const TotpStatusSchema = object({
|
|
|
12210
12571
|
object({ userId: string(), code: string() }),
|
|
12211
12572
|
object({ valid: boolean() }),
|
|
12212
12573
|
{ kind: "mutation", access: "view" }
|
|
12574
|
+
),
|
|
12575
|
+
// ── OAuth account-linking grant ────────────────────────────────
|
|
12576
|
+
//
|
|
12577
|
+
// Core's /oauth2/* endpoints delegate here. Tokens are sso-bridge
|
|
12578
|
+
// JWTs (kinds oauth-code / oauth-access / oauth-refresh) and ALWAYS
|
|
12579
|
+
// carry isAdmin:false — the operator login proves hub control; the
|
|
12580
|
+
// issued token is minimal (device scope only).
|
|
12581
|
+
oauthIssueCode: method(
|
|
12582
|
+
object({
|
|
12583
|
+
integrationId: string(),
|
|
12584
|
+
userId: string(),
|
|
12585
|
+
username: string(),
|
|
12586
|
+
scopes: array(TokenScopeSchema),
|
|
12587
|
+
redirectUri: string(),
|
|
12588
|
+
hubUrl: string()
|
|
12589
|
+
}),
|
|
12590
|
+
object({ code: string() }),
|
|
12591
|
+
{ kind: "mutation", access: "create" }
|
|
12592
|
+
),
|
|
12593
|
+
oauthExchangeCode: method(
|
|
12594
|
+
object({ code: string(), redirectUri: string() }),
|
|
12595
|
+
object({
|
|
12596
|
+
accessToken: string(),
|
|
12597
|
+
refreshToken: string(),
|
|
12598
|
+
expiresIn: number()
|
|
12599
|
+
}).nullable(),
|
|
12600
|
+
{ kind: "mutation", access: "view" }
|
|
12601
|
+
),
|
|
12602
|
+
oauthRefresh: method(
|
|
12603
|
+
object({ refreshToken: string() }),
|
|
12604
|
+
object({
|
|
12605
|
+
accessToken: string(),
|
|
12606
|
+
refreshToken: string(),
|
|
12607
|
+
expiresIn: number()
|
|
12608
|
+
}).nullable(),
|
|
12609
|
+
{ kind: "mutation", access: "view" }
|
|
12610
|
+
),
|
|
12611
|
+
oauthVerifyAccessToken: method(
|
|
12612
|
+
object({ token: string() }),
|
|
12613
|
+
object({
|
|
12614
|
+
userId: string(),
|
|
12615
|
+
username: string(),
|
|
12616
|
+
scopes: array(TokenScopeSchema)
|
|
12617
|
+
}).nullable(),
|
|
12618
|
+
{ access: "view" }
|
|
12619
|
+
),
|
|
12620
|
+
// ── OAuth linked-session management (Phase D) ──────────────────
|
|
12621
|
+
//
|
|
12622
|
+
// The admin UI lists active account-linking sessions and revokes
|
|
12623
|
+
// them; revocation makes the linked integration's tokens fail
|
|
12624
|
+
// verification immediately.
|
|
12625
|
+
listOauthSessions: method(
|
|
12626
|
+
_void(),
|
|
12627
|
+
array(OauthSessionSummarySchema),
|
|
12628
|
+
{ auth: "admin" }
|
|
12629
|
+
),
|
|
12630
|
+
revokeOauthSession: method(
|
|
12631
|
+
object({ id: string() }),
|
|
12632
|
+
object({ success: boolean() }),
|
|
12633
|
+
{ kind: "mutation", auth: "admin", access: "delete" }
|
|
12213
12634
|
)
|
|
12214
12635
|
}
|
|
12215
12636
|
});
|
|
@@ -12426,6 +12847,19 @@ const RenameNodeResultSchema = object({
|
|
|
12426
12847
|
record(string(), ClusterAddonStatusEntrySchema),
|
|
12427
12848
|
{ auth: "admin" }
|
|
12428
12849
|
),
|
|
12850
|
+
getCapUsageGraph: method(
|
|
12851
|
+
object({
|
|
12852
|
+
windowSeconds: number().int().positive().max(300).default(60)
|
|
12853
|
+
}),
|
|
12854
|
+
array(object({
|
|
12855
|
+
callerAddonId: string(),
|
|
12856
|
+
providerAddonId: string(),
|
|
12857
|
+
capName: string(),
|
|
12858
|
+
callsPerMin: number(),
|
|
12859
|
+
lastCallAtMs: number()
|
|
12860
|
+
})).readonly(),
|
|
12861
|
+
{ auth: "admin" }
|
|
12862
|
+
),
|
|
12429
12863
|
/**
|
|
12430
12864
|
* Direct per-node addon listing — calls `$agent.status` on the target
|
|
12431
12865
|
* node (or returns the hub registry for `nodeId === 'hub'`) and surfaces
|
|
@@ -13523,4 +13957,4 @@ exports.recordingEngineCapability = recordingEngineCapability;
|
|
|
13523
13957
|
exports.string = string;
|
|
13524
13958
|
exports.tuple = tuple;
|
|
13525
13959
|
exports.zoneAnalyticsCapability = zoneAnalyticsCapability;
|
|
13526
|
-
//# sourceMappingURL=index-
|
|
13960
|
+
//# sourceMappingURL=index-Dbx13pc7.js.map
|