@camstack/system 1.2.138 → 1.2.140

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 (60) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  14. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.js +3 -3
  16. package/dist/builtins/device-manager/device-manager.addon.mjs +3 -3
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +7 -0
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.js +15 -4
  19. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +15 -4
  20. package/dist/builtins/hub-forwarder/index.js +1 -1
  21. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  23. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  25. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  26. package/dist/builtins/local-network/local-network.addon.js +1 -1
  27. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  28. package/dist/builtins/loki-logging/index.js +1 -1
  29. package/dist/builtins/loki-logging/index.mjs +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  31. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  32. package/dist/builtins/platform-probe/index.js +1 -1
  33. package/dist/builtins/platform-probe/index.mjs +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  35. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  36. package/dist/builtins/snapshot/index.js +1 -1
  37. package/dist/builtins/snapshot/index.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  39. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/system-config/system-config.addon.js +1 -1
  45. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  46. package/dist/builtins/winston-logging/index.js +1 -1
  47. package/dist/builtins/winston-logging/index.mjs +1 -1
  48. package/dist/{dist-DMOTtKH8.mjs → dist-Clses4Bs.mjs} +111 -7
  49. package/dist/{dist-mQ3BkrJd.js → dist-D5Jhh8Vk.js} +116 -6
  50. package/dist/index.js +29 -18
  51. package/dist/index.mjs +30 -18
  52. package/dist/kernel/cap-router-builder.d.ts +13 -0
  53. package/dist/kernel/index.d.ts +1 -1
  54. package/dist/kernel/moleculer/trpc-links.d.ts +1 -12
  55. package/dist/kernel/transport/cap-route-resolver.d.ts +25 -1
  56. package/dist/{manifest-python-deps-C9x9vrqt.js → manifest-python-deps-Bu8H1_rg.js} +16 -49
  57. package/dist/{manifest-python-deps-08rqn6xN.mjs → manifest-python-deps-Dxifi-o0.mjs} +17 -44
  58. package/dist/{retired-settings-keys-CPRvyt-E.mjs → retired-settings-keys-Cr8N6C6X.mjs} +1 -1
  59. package/dist/{retired-settings-keys-Dvkcu_zf.js → retired-settings-keys-Dflres-F.js} +1 -1
  60. package/package.json +1 -1
@@ -2534,7 +2534,7 @@ function method(input, output, options) {
2534
2534
  input,
2535
2535
  output,
2536
2536
  kind: options?.kind ?? "query",
2537
- auth: options?.auth ?? "protected",
2537
+ ...options?.auth !== void 0 ? { auth: options.auth } : {},
2538
2538
  ...options?.access !== void 0 ? { access: options.access } : {},
2539
2539
  ...options?.caller !== void 0 ? { caller: options.caller } : {},
2540
2540
  timeoutMs: options?.timeoutMs
@@ -3838,10 +3838,11 @@ var RelocateFootageInputSchema = z.object({
3838
3838
  * `RecordingConfig.enabled` or camera wrapper bindings. */
3839
3839
  var StorageMigrationLeaseInputSchema = z.object({ leaseId: z.string().min(1) });
3840
3840
  var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: z.string().min(1) });
3841
- var StorageMigrationMediaMoveInputSchema = z.object({
3841
+ var RelocateMediaInputSchema = z.object({
3842
3842
  toLocationId: z.string(),
3843
3843
  throttleMbps: z.number().min(1).max(1e3).optional()
3844
- }).extend({ leaseId: z.string().min(1) });
3844
+ });
3845
+ var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: z.string().min(1) });
3845
3846
  /** The independently selectable logical storage classes. `recordings`
3846
3847
  * encompasses the high and mid segment profiles; `recordingsLow` is low
3847
3848
  * segments; `eventMedia` is post-analysis blobs. */
@@ -4136,7 +4137,26 @@ var LabelDefinitionSchema = z.object({
4136
4137
  description: z.string().optional(),
4137
4138
  icon: z.string().optional()
4138
4139
  });
4139
- var ClassMapDefinitionSchema = z.object({
4140
+ /**
4141
+ * Wire schema for a per-model CATALOG classMap override
4142
+ * (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
4143
+ * restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
4144
+ * detection pipeline executor actually routes.
4145
+ *
4146
+ * This is deliberately a DIFFERENT, narrower shape than the general-purpose
4147
+ * `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
4148
+ * and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
4149
+ * enum) — the two used to share the name `ClassMapDefinition`/
4150
+ * `ClassMapDefinitionSchema`, which made the schema-type-twin guard
4151
+ * (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
4152
+ * are not: it is two different concepts colliding on a name. Keep this type
4153
+ * under its own name rather than reusing `ClassMapDefinition` — reusing it
4154
+ * would either narrow every `ClassMapDefinition` consumer to the four
4155
+ * detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
4156
+ * schema exists for (see the "rejects a classMap whose target is not a
4157
+ * detection macro" test in `model-catalog-schema.test.ts`).
4158
+ */
4159
+ var DetectionCatalogClassMapSchema = z.object({
4140
4160
  mapping: z.record(z.string(), z.enum([
4141
4161
  "person",
4142
4162
  "vehicle",
@@ -4341,7 +4361,7 @@ var ModelCatalogEntrySchema = z.object({
4341
4361
  * applies (Frigate / COCO public catalog). Set on a custom model whose raw
4342
4362
  * labels already ARE the CamStack macros (Scrypted identity map).
4343
4363
  */
4344
- classMap: ClassMapDefinitionSchema.optional()
4364
+ classMap: DetectionCatalogClassMapSchema.optional()
4345
4365
  });
4346
4366
  var ConvertTargetSchema = z.discriminatedUnion("format", [z.object({
4347
4367
  format: z.literal("openvino"),
@@ -4371,7 +4391,7 @@ var ModelConvertMetadataSchema = z.object({
4371
4391
  "segmentation"
4372
4392
  ]),
4373
4393
  faceAlignment: z.boolean().optional(),
4374
- classMap: ClassMapDefinitionSchema.optional()
4394
+ classMap: DetectionCatalogClassMapSchema.optional()
4375
4395
  });
4376
4396
  var ConvertArtifactSchema = z.object({
4377
4397
  format: z.enum(MODEL_FORMATS),
@@ -7742,6 +7762,44 @@ function objectInputDeclaresAddonId(schema) {
7742
7762
  function resolveDefShape(defShape) {
7743
7763
  return typeof defShape === "function" ? defShape() : defShape;
7744
7764
  }
7765
+ /**
7766
+ * Effective auth for a cap method — the `internal: true` floor (Task 7.5c).
7767
+ *
7768
+ * `internal: true` on a cap def is a DECLARATION that its methods are for
7769
+ * in-process (`ctx.api`) consumption only. Nothing enforced that:
7770
+ * `resolveCapMount` never reads `internal` (an internal cap still gets a
7771
+ * full tRPC router), and a method that omitted an explicit `auth` used to
7772
+ * default — permanently, at `method()`-call time — to `'protected'`,
7773
+ * reachable by any authenticated session regardless of `internal`. That
7774
+ * silent default is how 45 procedures across 13 internal caps ended up
7775
+ * exposed, including `ssoBridge.signBridgeToken`: it accepted
7776
+ * caller-supplied claims (including `isAdmin`), was reachable by any
7777
+ * authenticated session, and its token is redeemed at
7778
+ * `/api/auth/sso/finish` to mint a session — a full privilege escalation.
7779
+ * See `docs/decisions/adr-0240-an-internal-cap-floors-its-unannotated-methods-to-admin.md`
7780
+ * (D240) for the record.
7781
+ *
7782
+ * The floor, exactly: an `internal` cap's method with NO explicit `auth`
7783
+ * resolves to `'admin'` instead of `'protected'`. A method that DELIBERATELY
7784
+ * declares an explicit `auth` — public, protected, or admin — keeps it
7785
+ * unconditionally; the author already said what they meant, and an
7786
+ * annotation that happens to agree with the floor is documentation, not
7787
+ * redundancy. A non-`internal` cap's un-annotated method is unaffected
7788
+ * (still `'protected'`). This is a FLOOR, not a hard `mount: 'skip'` — that
7789
+ * would also override a deliberate `auth: 'public'`/`'protected'` choice,
7790
+ * which is not the defect being closed.
7791
+ *
7792
+ * `method()` (`capability-definition.ts`) deliberately leaves `auth`
7793
+ * UNSET when the caller omits it (rather than defaulting there) so the
7794
+ * "was this explicit" bit survives to this single resolution point. Single
7795
+ * source of truth shared by the runtime builder (`cap-router-builder.ts`)
7796
+ * and the codegen (`generate-cap-routers.ts`, `gen-api-reference.ts`) — the
7797
+ * two must never disagree, a documented failure mode in this repo.
7798
+ */
7799
+ function resolveMethodAuth(def, method) {
7800
+ if (method.auth !== void 0) return method.auth;
7801
+ return def.internal === true ? "admin" : "protected";
7802
+ }
7745
7803
  /** Auth level → base-procedure key. `superAdmin` collapses to `admin`. */
7746
7804
  function procedureAuthKey(auth) {
7747
7805
  if (auth === "public") return "public";
@@ -15880,6 +15938,29 @@ var pipelineAnalyticsCapability = {
15880
15938
  kind: "mutation",
15881
15939
  auth: "admin"
15882
15940
  }),
15941
+ /**
15942
+ * Moves event media between locations — the OPERATOR's mover, without the
15943
+ * coordinator's lease. Twin of `recording.relocateFootage`: the same
15944
+ * engine the lease-gated coordinated migration uses
15945
+ * (`startStorageMigrationMove`), armable in the background and WITHOUT
15946
+ * pausing anything. Exists because `eventMedia` was the only storage
15947
+ * class whose only move path went through the recorder's global pause.
15948
+ */
15949
+ relocateMedia: method(RelocateMediaInputSchema, z.object({ jobId: z.string() }), {
15950
+ kind: "mutation",
15951
+ auth: "admin"
15952
+ }),
15953
+ /** Every relocate job this addon knows about, newest first (in RAM: the
15954
+ * move is resumable, so a lost list costs nothing but the display). */
15955
+ listRelocateMediaJobs: method(z.object({}), z.array(RelocateJobSchema).readonly(), {
15956
+ kind: "query",
15957
+ auth: "admin"
15958
+ }),
15959
+ /** Cancel a running or queued relocate job. */
15960
+ cancelRelocateMedia: method(z.object({ jobId: z.string() }), z.object({ cancelled: z.boolean() }), {
15961
+ kind: "mutation",
15962
+ auth: "admin"
15963
+ }),
15883
15964
  listOpsLog: method(OpsLogQueryInputSchema, z.array(OpsLogEntrySchema).readonly(), {
15884
15965
  kind: "query",
15885
15966
  auth: "admin"
@@ -16239,6 +16320,11 @@ z.object({
16239
16320
  "jpeg"
16240
16321
  ])
16241
16322
  });
16323
+ /**
16324
+ * Process-local frame identity. It is serializable so it can ride an in-process
16325
+ * capability call, but `registryId` deliberately prevents resolution in any
16326
+ * other process or execution group.
16327
+ */
16242
16328
  var FrameRefSchema = z.object({
16243
16329
  registryId: z.string().min(1),
16244
16330
  id: z.string().min(1),
@@ -33934,6 +34020,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33934
34020
  addonId: null,
33935
34021
  access: "create"
33936
34022
  },
34023
+ "pipelineAnalytics.cancelRelocateMedia": {
34024
+ capName: "pipeline-analytics",
34025
+ capScope: "device",
34026
+ addonId: null,
34027
+ access: "create"
34028
+ },
33937
34029
  "pipelineAnalytics.cancelStorageMigrationMove": {
33938
34030
  capName: "pipeline-analytics",
33939
34031
  capScope: "device",
@@ -34108,6 +34200,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34108
34200
  addonId: null,
34109
34201
  access: "view"
34110
34202
  },
34203
+ "pipelineAnalytics.listRelocateMediaJobs": {
34204
+ capName: "pipeline-analytics",
34205
+ capScope: "device",
34206
+ addonId: null,
34207
+ access: "view"
34208
+ },
34111
34209
  "pipelineAnalytics.listRetrainAnnotations": {
34112
34210
  capName: "pipeline-analytics",
34113
34211
  capScope: "device",
@@ -34186,6 +34284,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34186
34284
  addonId: null,
34187
34285
  access: "create"
34188
34286
  },
34287
+ "pipelineAnalytics.relocateMedia": {
34288
+ capName: "pipeline-analytics",
34289
+ capScope: "device",
34290
+ addonId: null,
34291
+ access: "create"
34292
+ },
34189
34293
  "pipelineAnalytics.restageRetrainTrack": {
34190
34294
  capName: "pipeline-analytics",
34191
34295
  capScope: "device",
@@ -39238,4 +39342,4 @@ function enumerateInferenceDevices(hw) {
39238
39342
  return out;
39239
39343
  }
39240
39344
  //#endregion
39241
- export { metricsProviderCapability as $, dataStoreProviderCapability as A, asNumber as At, extractNestedAddonId as B, parseJsonUnknown as Bt, backupCapability as C, DeviceFeature as Ct, coreBlockAddonId as D, ReadinessTimeoutError as Dt, buildStreamParamsConfigSchema as E, ReadinessRegistry as Et, deviceStatusCapability as F, expandCapMethods as Ft, isSameAddonId as G, EventCategory as Gt, isArrayOutputSchema as H, resolveCapMount as Ht, doorbellCapability as I, hydrateSchema as It, lifecycleJobSchema as J, isVoidInput as K, enumerateInferenceDevices as L, isDeviceConfigCap as Lt, deriveBatteryPresence as M, createEvent as Mt, deviceManagerCapability as N, emitDownForOwnedCaps as Nt, coreBlockIdFromAddonId as O, WELL_KNOWN_TAB_MAP as Ot, deviceStateCapability as P, emitReadiness as Pt, looseSchema as Q, enumerateItemArrayFields as R, nodePin as Rt, authProviderCapability as S, DEVICE_STATUS_METHOD as St, batteryCapability as T, DeviceType as Tt, isCollectionArrayMethod as U, scopeKey as Ut, filesystemBrowseCapability as V, readinessKey as Vt, isObjectInput as W, sleep as Wt, logDestinationCapability as X, localNetworkCapability as Y, logLevelAtMost as Z, UserRecordSchema as _, vectorStoreCapability as _t, CAP_NAMES_WITH_STATUS as a, runtimeStatePolicyFor as at, addonWidgetsCapability as b, DATAPLANE_SECRET_HEADER as bt, CoreBlockSchema as c, scoreRuntimes as ct, METHOD_ACCESS_MAP as d, storageCapability as dt, normalizeUnit as et, RUNTIME_DEFAULTS as f, storageMigrationCapability as ft, StorageMigrationJobSchema as g, vectorDimFromBase64 as gt, StorageLocationTypeSchema as h, userManagementCapability as ht, BatteryStatusSchema as i, procedureAuthKey as it, decodeVectorBase64 as j, asString as jt, coreBlocksCapability as k, asJsonObject as kt, DeclaredDevices as l, settingsStoreCapability as lt, ScopedTokenSchema as m, streamQualityLabel as mt, AlertSchema as n, parseStreamParamsFormPatch as nt, CORE_BLOCKS_ADDON_ID as o, scopesAllowAddon as ot, STREAM_PROFILE_META as p, storageProviderCapability as pt, kebabToCamel as q, ApiKeyRecordSchema as r, platformProbeCapability as rt, CORE_BLOCK_ADDON_PREFIX as s, scopesAllowDeviceCap as st, ALL_CAPABILITY_DEFINITIONS as t, objectInputDeclaresAddonId as tt, DeviceStatusSchema as u, snapshotCapability as ut, addonPagesCapability as v, errMsg as vt, bareAddonId as w, DeviceRole as wt, alertsCapability as x, DEVICE_SETTINGS_CONTRIBUTION_METHODS as xt, addonSettingsCapability as y, BaseAddon as yt, enumerateSchemaFields as z, parseJsonObject as zt };
39345
+ export { metricsProviderCapability as $, dataStoreProviderCapability as A, asJsonObject as At, extractNestedAddonId as B, parseJsonObject as Bt, backupCapability as C, DEVICE_STATUS_METHOD as Ct, coreBlockAddonId as D, ReadinessRegistry as Dt, buildStreamParamsConfigSchema as E, DeviceType as Et, deviceStatusCapability as F, emitReadiness as Ft, isSameAddonId as G, sleep as Gt, isArrayOutputSchema as H, readinessKey as Ht, doorbellCapability as I, expandCapMethods as It, lifecycleJobSchema as J, isVoidInput as K, EventCategory as Kt, enumerateInferenceDevices as L, hydrateSchema as Lt, deriveBatteryPresence as M, asString as Mt, deviceManagerCapability as N, createEvent as Nt, coreBlockIdFromAddonId as O, ReadinessTimeoutError as Ot, deviceStateCapability as P, emitDownForOwnedCaps as Pt, looseSchema as Q, enumerateItemArrayFields as R, isDeviceConfigCap as Rt, authProviderCapability as S, DEVICE_SETTINGS_CONTRIBUTION_METHODS as St, batteryCapability as T, DeviceRole as Tt, isCollectionArrayMethod as U, resolveCapMount as Ut, filesystemBrowseCapability as V, parseJsonUnknown as Vt, isObjectInput as W, scopeKey as Wt, logDestinationCapability as X, localNetworkCapability as Y, logLevelAtMost as Z, UserRecordSchema as _, vectorDimFromBase64 as _t, CAP_NAMES_WITH_STATUS as a, resolveMethodAuth as at, addonWidgetsCapability as b, BaseAddon as bt, CoreBlockSchema as c, scopesAllowDeviceCap as ct, METHOD_ACCESS_MAP as d, snapshotCapability as dt, normalizeUnit as et, RUNTIME_DEFAULTS as f, storageCapability as ft, StorageMigrationJobSchema as g, userManagementCapability as gt, StorageLocationTypeSchema as h, streamQualityLabel as ht, BatteryStatusSchema as i, procedureAuthKey as it, decodeVectorBase64 as j, asNumber as jt, coreBlocksCapability as k, WELL_KNOWN_TAB_MAP as kt, DeclaredDevices as l, scoreRuntimes as lt, ScopedTokenSchema as m, storageProviderCapability as mt, AlertSchema as n, parseStreamParamsFormPatch as nt, CORE_BLOCKS_ADDON_ID as o, runtimeStatePolicyFor as ot, STREAM_PROFILE_META as p, storageMigrationCapability as pt, kebabToCamel as q, ApiKeyRecordSchema as r, platformProbeCapability as rt, CORE_BLOCK_ADDON_PREFIX as s, scopesAllowAddon as st, ALL_CAPABILITY_DEFINITIONS as t, objectInputDeclaresAddonId as tt, DeviceStatusSchema as u, settingsStoreCapability as ut, addonPagesCapability as v, vectorStoreCapability as vt, bareAddonId as w, DeviceFeature as wt, alertsCapability as x, DATAPLANE_SECRET_HEADER as xt, addonSettingsCapability as y, errMsg as yt, enumerateSchemaFields as z, nodePin as zt };
@@ -2534,7 +2534,7 @@ function method(input, output, options) {
2534
2534
  input,
2535
2535
  output,
2536
2536
  kind: options?.kind ?? "query",
2537
- auth: options?.auth ?? "protected",
2537
+ ...options?.auth !== void 0 ? { auth: options.auth } : {},
2538
2538
  ...options?.access !== void 0 ? { access: options.access } : {},
2539
2539
  ...options?.caller !== void 0 ? { caller: options.caller } : {},
2540
2540
  timeoutMs: options?.timeoutMs
@@ -3838,10 +3838,11 @@ var RelocateFootageInputSchema = zod.z.object({
3838
3838
  * `RecordingConfig.enabled` or camera wrapper bindings. */
3839
3839
  var StorageMigrationLeaseInputSchema = zod.z.object({ leaseId: zod.z.string().min(1) });
3840
3840
  var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: zod.z.string().min(1) });
3841
- var StorageMigrationMediaMoveInputSchema = zod.z.object({
3841
+ var RelocateMediaInputSchema = zod.z.object({
3842
3842
  toLocationId: zod.z.string(),
3843
3843
  throttleMbps: zod.z.number().min(1).max(1e3).optional()
3844
- }).extend({ leaseId: zod.z.string().min(1) });
3844
+ });
3845
+ var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: zod.z.string().min(1) });
3845
3846
  /** The independently selectable logical storage classes. `recordings`
3846
3847
  * encompasses the high and mid segment profiles; `recordingsLow` is low
3847
3848
  * segments; `eventMedia` is post-analysis blobs. */
@@ -4136,7 +4137,26 @@ var LabelDefinitionSchema = zod.z.object({
4136
4137
  description: zod.z.string().optional(),
4137
4138
  icon: zod.z.string().optional()
4138
4139
  });
4139
- var ClassMapDefinitionSchema = zod.z.object({
4140
+ /**
4141
+ * Wire schema for a per-model CATALOG classMap override
4142
+ * (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
4143
+ * restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
4144
+ * detection pipeline executor actually routes.
4145
+ *
4146
+ * This is deliberately a DIFFERENT, narrower shape than the general-purpose
4147
+ * `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
4148
+ * and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
4149
+ * enum) — the two used to share the name `ClassMapDefinition`/
4150
+ * `ClassMapDefinitionSchema`, which made the schema-type-twin guard
4151
+ * (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
4152
+ * are not: it is two different concepts colliding on a name. Keep this type
4153
+ * under its own name rather than reusing `ClassMapDefinition` — reusing it
4154
+ * would either narrow every `ClassMapDefinition` consumer to the four
4155
+ * detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
4156
+ * schema exists for (see the "rejects a classMap whose target is not a
4157
+ * detection macro" test in `model-catalog-schema.test.ts`).
4158
+ */
4159
+ var DetectionCatalogClassMapSchema = zod.z.object({
4140
4160
  mapping: zod.z.record(zod.z.string(), zod.z.enum([
4141
4161
  "person",
4142
4162
  "vehicle",
@@ -4341,7 +4361,7 @@ var ModelCatalogEntrySchema = zod.z.object({
4341
4361
  * applies (Frigate / COCO public catalog). Set on a custom model whose raw
4342
4362
  * labels already ARE the CamStack macros (Scrypted identity map).
4343
4363
  */
4344
- classMap: ClassMapDefinitionSchema.optional()
4364
+ classMap: DetectionCatalogClassMapSchema.optional()
4345
4365
  });
4346
4366
  var ConvertTargetSchema = zod.z.discriminatedUnion("format", [zod.z.object({
4347
4367
  format: zod.z.literal("openvino"),
@@ -4371,7 +4391,7 @@ var ModelConvertMetadataSchema = zod.z.object({
4371
4391
  "segmentation"
4372
4392
  ]),
4373
4393
  faceAlignment: zod.z.boolean().optional(),
4374
- classMap: ClassMapDefinitionSchema.optional()
4394
+ classMap: DetectionCatalogClassMapSchema.optional()
4375
4395
  });
4376
4396
  var ConvertArtifactSchema = zod.z.object({
4377
4397
  format: zod.z.enum(MODEL_FORMATS),
@@ -7742,6 +7762,44 @@ function objectInputDeclaresAddonId(schema) {
7742
7762
  function resolveDefShape(defShape) {
7743
7763
  return typeof defShape === "function" ? defShape() : defShape;
7744
7764
  }
7765
+ /**
7766
+ * Effective auth for a cap method — the `internal: true` floor (Task 7.5c).
7767
+ *
7768
+ * `internal: true` on a cap def is a DECLARATION that its methods are for
7769
+ * in-process (`ctx.api`) consumption only. Nothing enforced that:
7770
+ * `resolveCapMount` never reads `internal` (an internal cap still gets a
7771
+ * full tRPC router), and a method that omitted an explicit `auth` used to
7772
+ * default — permanently, at `method()`-call time — to `'protected'`,
7773
+ * reachable by any authenticated session regardless of `internal`. That
7774
+ * silent default is how 45 procedures across 13 internal caps ended up
7775
+ * exposed, including `ssoBridge.signBridgeToken`: it accepted
7776
+ * caller-supplied claims (including `isAdmin`), was reachable by any
7777
+ * authenticated session, and its token is redeemed at
7778
+ * `/api/auth/sso/finish` to mint a session — a full privilege escalation.
7779
+ * See `docs/decisions/adr-0240-an-internal-cap-floors-its-unannotated-methods-to-admin.md`
7780
+ * (D240) for the record.
7781
+ *
7782
+ * The floor, exactly: an `internal` cap's method with NO explicit `auth`
7783
+ * resolves to `'admin'` instead of `'protected'`. A method that DELIBERATELY
7784
+ * declares an explicit `auth` — public, protected, or admin — keeps it
7785
+ * unconditionally; the author already said what they meant, and an
7786
+ * annotation that happens to agree with the floor is documentation, not
7787
+ * redundancy. A non-`internal` cap's un-annotated method is unaffected
7788
+ * (still `'protected'`). This is a FLOOR, not a hard `mount: 'skip'` — that
7789
+ * would also override a deliberate `auth: 'public'`/`'protected'` choice,
7790
+ * which is not the defect being closed.
7791
+ *
7792
+ * `method()` (`capability-definition.ts`) deliberately leaves `auth`
7793
+ * UNSET when the caller omits it (rather than defaulting there) so the
7794
+ * "was this explicit" bit survives to this single resolution point. Single
7795
+ * source of truth shared by the runtime builder (`cap-router-builder.ts`)
7796
+ * and the codegen (`generate-cap-routers.ts`, `gen-api-reference.ts`) — the
7797
+ * two must never disagree, a documented failure mode in this repo.
7798
+ */
7799
+ function resolveMethodAuth(def, method) {
7800
+ if (method.auth !== void 0) return method.auth;
7801
+ return def.internal === true ? "admin" : "protected";
7802
+ }
7745
7803
  /** Auth level → base-procedure key. `superAdmin` collapses to `admin`. */
7746
7804
  function procedureAuthKey(auth) {
7747
7805
  if (auth === "public") return "public";
@@ -15880,6 +15938,29 @@ var pipelineAnalyticsCapability = {
15880
15938
  kind: "mutation",
15881
15939
  auth: "admin"
15882
15940
  }),
15941
+ /**
15942
+ * Moves event media between locations — the OPERATOR's mover, without the
15943
+ * coordinator's lease. Twin of `recording.relocateFootage`: the same
15944
+ * engine the lease-gated coordinated migration uses
15945
+ * (`startStorageMigrationMove`), armable in the background and WITHOUT
15946
+ * pausing anything. Exists because `eventMedia` was the only storage
15947
+ * class whose only move path went through the recorder's global pause.
15948
+ */
15949
+ relocateMedia: method(RelocateMediaInputSchema, zod.z.object({ jobId: zod.z.string() }), {
15950
+ kind: "mutation",
15951
+ auth: "admin"
15952
+ }),
15953
+ /** Every relocate job this addon knows about, newest first (in RAM: the
15954
+ * move is resumable, so a lost list costs nothing but the display). */
15955
+ listRelocateMediaJobs: method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
15956
+ kind: "query",
15957
+ auth: "admin"
15958
+ }),
15959
+ /** Cancel a running or queued relocate job. */
15960
+ cancelRelocateMedia: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
15961
+ kind: "mutation",
15962
+ auth: "admin"
15963
+ }),
15883
15964
  listOpsLog: method(OpsLogQueryInputSchema, zod.z.array(OpsLogEntrySchema).readonly(), {
15884
15965
  kind: "query",
15885
15966
  auth: "admin"
@@ -16239,6 +16320,11 @@ zod.z.object({
16239
16320
  "jpeg"
16240
16321
  ])
16241
16322
  });
16323
+ /**
16324
+ * Process-local frame identity. It is serializable so it can ride an in-process
16325
+ * capability call, but `registryId` deliberately prevents resolution in any
16326
+ * other process or execution group.
16327
+ */
16242
16328
  var FrameRefSchema = zod.z.object({
16243
16329
  registryId: zod.z.string().min(1),
16244
16330
  id: zod.z.string().min(1),
@@ -33934,6 +34020,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
33934
34020
  addonId: null,
33935
34021
  access: "create"
33936
34022
  },
34023
+ "pipelineAnalytics.cancelRelocateMedia": {
34024
+ capName: "pipeline-analytics",
34025
+ capScope: "device",
34026
+ addonId: null,
34027
+ access: "create"
34028
+ },
33937
34029
  "pipelineAnalytics.cancelStorageMigrationMove": {
33938
34030
  capName: "pipeline-analytics",
33939
34031
  capScope: "device",
@@ -34108,6 +34200,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34108
34200
  addonId: null,
34109
34201
  access: "view"
34110
34202
  },
34203
+ "pipelineAnalytics.listRelocateMediaJobs": {
34204
+ capName: "pipeline-analytics",
34205
+ capScope: "device",
34206
+ addonId: null,
34207
+ access: "view"
34208
+ },
34111
34209
  "pipelineAnalytics.listRetrainAnnotations": {
34112
34210
  capName: "pipeline-analytics",
34113
34211
  capScope: "device",
@@ -34186,6 +34284,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
34186
34284
  addonId: null,
34187
34285
  access: "create"
34188
34286
  },
34287
+ "pipelineAnalytics.relocateMedia": {
34288
+ capName: "pipeline-analytics",
34289
+ capScope: "device",
34290
+ addonId: null,
34291
+ access: "create"
34292
+ },
34189
34293
  "pipelineAnalytics.restageRetrainTrack": {
34190
34294
  capName: "pipeline-analytics",
34191
34295
  capScope: "device",
@@ -39742,6 +39846,12 @@ Object.defineProperty(exports, "resolveCapMount", {
39742
39846
  return resolveCapMount;
39743
39847
  }
39744
39848
  });
39849
+ Object.defineProperty(exports, "resolveMethodAuth", {
39850
+ enumerable: true,
39851
+ get: function() {
39852
+ return resolveMethodAuth;
39853
+ }
39854
+ });
39745
39855
  Object.defineProperty(exports, "runtimeStatePolicyFor", {
39746
39856
  enumerable: true,
39747
39857
  get: function() {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-mQ3BkrJd.js");
3
+ const require_dist = require("./dist-D5Jhh8Vk.js");
4
4
  const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
5
5
  require("./builtins/alerts/index.js");
6
6
  const require_formatter = require("./formatter-DqAKDlvN.js");
@@ -26,7 +26,7 @@ require("./builtins/system-config/index.js");
26
26
  const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
27
27
  const require_file_data_plane = require("./file-data-plane-DO8KbxCe.js");
28
28
  const require_tls$1 = require("./tls-u8QCJCFE.js");
29
- const require_manifest_python_deps = require("./manifest-python-deps-C9x9vrqt.js");
29
+ const require_manifest_python_deps = require("./manifest-python-deps-Bu8H1_rg.js");
30
30
  const require_resource_monitor = require("./resource-monitor-CdnzxBLP.js");
31
31
  const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
32
32
  let zod = require("zod");
@@ -6406,15 +6406,35 @@ function methodsFor(def) {
6406
6406
  return {
6407
6407
  name,
6408
6408
  kind: m.kind ?? "query",
6409
- auth: m.auth ?? "protected",
6409
+ auth: require_dist.resolveMethodAuth(def, m),
6410
6410
  schema: m,
6411
6411
  isVoid: require_dist.isVoidInput(m.input),
6412
6412
  isObject: require_dist.isObjectInput(m.input),
6413
- callerRequired: m.caller === "required"
6413
+ callerRequired: m.caller === "required",
6414
+ isArrayOutput: m.kind !== "subscription" && require_dist.isArrayOutputSchema(m.output)
6414
6415
  };
6415
6416
  });
6416
6417
  }
6417
6418
  /**
6419
+ * Invoke `method.name` on a resolved provider, raising the canonical
6420
+ * "method not found" error (Task 7.5d) when the provider does not implement
6421
+ * it — the naive `provider[method.name]?.(payload)` optional call let a
6422
+ * missing method answer `undefined` (200 to the caller). EXCEPTION, mirrored
6423
+ * from `child-cap-dispatch.ts`'s `isCollectionListMethod` graceful skip: a
6424
+ * COLLECTION cap's array-output method degrades to `[]` — the hub fans that
6425
+ * method across every registered provider
6426
+ * (`resolveCollectionProvider`/`concatArrayMethod`), so ONE provider not
6427
+ * implementing it is a graceful skip, not an error. Every other missing
6428
+ * method (singleton, device-native, or a collection's SCALAR method) is a
6429
+ * real implementation gap and fails loud.
6430
+ */
6431
+ function invokeCapMethod(provider, method, payload, capName, isCollection, services) {
6432
+ const fn = provider[method.name];
6433
+ if (typeof fn === "function") return fn(payload);
6434
+ if (isCollection && method.isArrayOutput) return [];
6435
+ return (services.methodNotFound ?? ((cap, m) => services.badRequest(`Capability "${cap}" has no method "${m}"`)))(capName, method.name);
6436
+ }
6437
+ /**
6418
6438
  * Extract the authenticated caller identity from the (structurally
6419
6439
  * unknown) tRPC context. The builder cannot import the server's
6420
6440
  * `TrpcContext`, so the read is narrowing-based: `ctx.user.id` (string)
@@ -6534,37 +6554,29 @@ function buildOneCapRouter(def, primitives, services) {
6534
6554
  }).optional() : zod.z.object({ nodeId: zod.z.string().optional() }).optional();
6535
6555
  procedures[method.name] = base.input(voidSelector)[procKind](({ input, ctx }) => {
6536
6556
  const sel = input ?? {};
6537
- return (nodeIdData ? requireLocal(capName, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services) : resolveProviderForCall(capName, sel.nodeId, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services, isCollection ? sel.addonId : void 0))[method.name]?.();
6557
+ return invokeCapMethod(nodeIdData ? requireLocal(capName, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services) : resolveProviderForCall(capName, sel.nodeId, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services, isCollection ? sel.addonId : void 0), method, void 0, capName, isCollection, services);
6538
6558
  });
6539
6559
  continue;
6540
6560
  }
6541
6561
  if (method.isObject) {
6542
6562
  const schema = nodeIdData ? inputSchema : require_dist.looseSchema(inputSchema);
6543
6563
  procedures[method.name] = base.input(schema)[procKind](({ input, ctx }) => {
6544
- if (nodeIdData) {
6545
- const provider = requireLocal(capName, () => getLocal(ctx), services);
6546
- const payload = method.callerRequired ? injectCaller(stripKeys(input, []).rest, ctx, capName, method.name, services) : input;
6547
- return provider[method.name]?.(payload);
6548
- }
6564
+ if (nodeIdData) return invokeCapMethod(requireLocal(capName, () => getLocal(ctx), services), method, method.callerRequired ? injectCaller(stripKeys(input, []).rest, ctx, capName, method.name, services) : input, capName, isCollection, services);
6549
6565
  if (isCollection) {
6550
6566
  const { rest, picked } = stripKeys(input, ["nodeId", "addonId"]);
6551
6567
  const nodeId = typeof picked.nodeId === "string" ? picked.nodeId : void 0;
6552
6568
  const topLevelAddonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
6553
6569
  const canRecoverNestedAddonId = !require_dist.isArrayOutputSchema(method.schema.output) && !require_dist.objectInputDeclaresAddonId(method.schema.input);
6554
6570
  const addonId = topLevelAddonId ?? (canRecoverNestedAddonId ? require_dist.extractNestedAddonId(rest) : void 0);
6555
- const provider = resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services, topLevelAddonId);
6556
- const payload = method.callerRequired ? injectCaller(rest, ctx, capName, method.name, services) : rest;
6557
- return provider[method.name]?.(payload);
6571
+ return invokeCapMethod(resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services, topLevelAddonId), method, method.callerRequired ? injectCaller(rest, ctx, capName, method.name, services) : rest, capName, isCollection, services);
6558
6572
  }
6559
6573
  const { rest, picked } = stripKeys(input, ["nodeId"]);
6560
- const provider = resolveProviderForCall(capName, typeof picked.nodeId === "string" ? picked.nodeId : void 0, () => getLocal(ctx), services);
6561
- const payload = method.callerRequired ? injectCaller(rest, ctx, capName, method.name, services) : rest;
6562
- return provider[method.name]?.(payload);
6574
+ return invokeCapMethod(resolveProviderForCall(capName, typeof picked.nodeId === "string" ? picked.nodeId : void 0, () => getLocal(ctx), services), method, method.callerRequired ? injectCaller(rest, ctx, capName, method.name, services) : rest, capName, isCollection, services);
6563
6575
  });
6564
6576
  continue;
6565
6577
  }
6566
6578
  procedures[method.name] = base.input(inputSchema)[procKind](({ input, ctx }) => {
6567
- return requireLocal(capName, () => getLocal(ctx), services)[method.name]?.(input);
6579
+ return invokeCapMethod(requireLocal(capName, () => getLocal(ctx), services), method, input, capName, isCollection, services);
6568
6580
  });
6569
6581
  }
6570
6582
  return primitives.router(procedures);
@@ -95389,7 +95401,6 @@ Object.defineProperty(exports, "installPythonRequirements", {
95389
95401
  return _camstack_types_node.installPythonRequirements;
95390
95402
  }
95391
95403
  });
95392
- exports.ipcChildLink = require_manifest_python_deps.ipcChildLink;
95393
95404
  exports.ipcParentLink = require_manifest_python_deps.ipcParentLink;
95394
95405
  exports.isAddonDeploySource = isAddonDeploySource;
95395
95406
  exports.isArrayOutputSchema = require_dist.isArrayOutputSchema;