@camstack/types 1.2.7 → 1.2.8

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.
@@ -86,6 +86,7 @@ export { networkAccessCapability } from '../capabilities/network-access.cap.js';
86
86
  export { networkQualityCapability } from '../capabilities/network-quality.cap.js';
87
87
  export { nodesCapability } from '../capabilities/nodes.cap.js';
88
88
  export { notificationOutputCapability } from '../capabilities/notification-output.cap.js';
89
+ export { notificationRulesCapability } from '../capabilities/notification-rules.cap.js';
89
90
  export { notifierCapability } from '../capabilities/notifier.cap.js';
90
91
  export { numericSensorCapability } from '../capabilities/numeric-sensor.cap.js';
91
92
  export { oauthIntegrationCapability } from '../capabilities/oauth-integration.cap.js';
@@ -229,6 +230,7 @@ export declare const CAPABILITY_NAMES: {
229
230
  readonly networkQuality: "network-quality";
230
231
  readonly nodes: "nodes";
231
232
  readonly notificationOutput: "notification-output";
233
+ readonly notificationRules: "notification-rules";
232
234
  readonly notifier: "notifier";
233
235
  readonly numericSensor: "numeric-sensor";
234
236
  readonly oauthIntegration: "oauth-integration";
@@ -385,6 +387,7 @@ export interface CapabilityRouterMap<TRouter = unknown> {
385
387
  readonly networkQuality: TRouter;
386
388
  readonly nodes: TRouter;
387
389
  readonly notificationOutput: TRouter;
390
+ readonly notificationRules: TRouter;
388
391
  readonly notifier: TRouter;
389
392
  readonly numericSensor: TRouter;
390
393
  readonly oauthIntegration: TRouter;
@@ -440,8 +443,8 @@ export interface CapabilityRouterMap<TRouter = unknown> {
440
443
  readonly zoneRules: TRouter;
441
444
  readonly zones: TRouter;
442
445
  }
443
- /** Capability names whose mode is `singleton` (120 caps). */
444
- export declare const SINGLETON_CAPABILITY_NAMES: readonly ["accessories", "addon-pages", "addon-settings", "addon-widgets", "addons", "admin-ui", "advanced-notifier", "air-quality-sensor", "alarm-panel", "alerts", "ambient-light-sensor", "audio-analysis", "audio-analyzer", "audio-codec", "audio-metrics", "automation-control", "backup", "battery", "binary", "brightness", "button", "camera-credentials", "camera-pipeline-config", "camera-streams", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "decoder", "detection-pipeline", "device-adoption", "device-discovery", "device-manager", "device-ops", "device-state", "device-status", "doorbell", "enum-sensor", "event-emitter", "events", "face-gallery", "fan-control", "feature-probe", "filesystem-browse", "flood", "gas", "humidifier", "humidity-sensor", "image", "image-settings", "integrations", "intercom", "lawn-mower-control", "llm-runtime", "local-network", "lock-control", "media-player", "metrics-provider", "model-convert", "model-distributor", "motion", "motion-detection", "motion-trigger", "motion-zones", "native-object-detection", "network-quality", "nodes", "notifier", "numeric-sensor", "osd", "pet-feeder", "pipeline-analytics", "pipeline-executor", "pipeline-orchestrator", "pipeline-runner", "plate-gallery", "platform-probe", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "reboot", "recording", "recordingExport", "scene-monitor", "script-runner", "server-management", "settings-store", "smoke", "snapshot", "sso-bridge", "storage", "stream-broker", "stream-catalog", "stream-params", "switch", "system", "tamper", "temperature-sensor", "toast", "update", "user-management", "vacuum-control", "valve", "vibration", "videoclips", "viewer-ui", "water-heater", "weather", "webrtc-session", "zone-analytics", "zone-rules", "zones"];
446
+ /** Capability names whose mode is `singleton` (121 caps). */
447
+ export declare const SINGLETON_CAPABILITY_NAMES: readonly ["accessories", "addon-pages", "addon-settings", "addon-widgets", "addons", "admin-ui", "advanced-notifier", "air-quality-sensor", "alarm-panel", "alerts", "ambient-light-sensor", "audio-analysis", "audio-analyzer", "audio-codec", "audio-metrics", "automation-control", "backup", "battery", "binary", "brightness", "button", "camera-credentials", "camera-pipeline-config", "camera-streams", "carbon-monoxide", "climate-control", "color", "connectivity", "consumables", "contact", "control", "cover", "day-night", "decoder", "detection-pipeline", "device-adoption", "device-discovery", "device-manager", "device-ops", "device-state", "device-status", "doorbell", "enum-sensor", "event-emitter", "events", "face-gallery", "fan-control", "feature-probe", "filesystem-browse", "flood", "gas", "humidifier", "humidity-sensor", "image", "image-settings", "integrations", "intercom", "lawn-mower-control", "llm-runtime", "local-network", "lock-control", "media-player", "metrics-provider", "model-convert", "model-distributor", "motion", "motion-detection", "motion-trigger", "motion-zones", "native-object-detection", "network-quality", "nodes", "notification-rules", "notifier", "numeric-sensor", "osd", "pet-feeder", "pipeline-analytics", "pipeline-executor", "pipeline-orchestrator", "pipeline-runner", "plate-gallery", "platform-probe", "power-meter", "presence", "pressure-sensor", "privacy-mask", "ptz", "ptz-autotrack", "reboot", "recording", "recordingExport", "scene-monitor", "script-runner", "server-management", "settings-store", "smoke", "snapshot", "sso-bridge", "storage", "stream-broker", "stream-catalog", "stream-params", "switch", "system", "tamper", "temperature-sensor", "toast", "update", "user-management", "vacuum-control", "valve", "vibration", "videoclips", "viewer-ui", "water-heater", "weather", "webrtc-session", "zone-analytics", "zone-rules", "zones"];
445
448
  /** Union of singleton capability names (literal string union). */
446
449
  export type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number];
447
450
  /** Capability names whose mode is `collection` (22 caps). */
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 802 method paths across 116 capabilities.
9
+ * Coverage: 810 method paths across 117 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -26,6 +26,7 @@ import type { networkAccessCapability } from '../capabilities/network-access.cap
26
26
  import type { networkQualityCapability } from '../capabilities/network-quality.cap.js';
27
27
  import type { nodesCapability } from '../capabilities/nodes.cap.js';
28
28
  import type { notificationOutputCapability } from '../capabilities/notification-output.cap.js';
29
+ import type { notificationRulesCapability } from '../capabilities/notification-rules.cap.js';
29
30
  import type { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js';
30
31
  import type { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js';
31
32
  import type { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js';
@@ -75,6 +76,7 @@ export interface SystemProxy {
75
76
  readonly networkQuality: Pick<InferProvider<typeof networkQualityCapability>, 'getAllStats'>;
76
77
  readonly nodes: Pick<InferProvider<typeof nodesCapability>, 'topology' | 'deployAddon' | 'undeployAddon' | 'restartAddon' | 'restartProcess' | 'restartNode' | 'shutdownNode' | 'renameNode' | 'clusterAddonStatus' | 'getCapUsageGraph' | 'getNodeAddons' | 'setProcessLogLevel' | 'executeQuery'>;
77
78
  readonly notificationOutput: Pick<InferProvider<typeof notificationOutputCapability>, 'listTargetKinds' | 'listTargets' | 'discoverTargets' | 'send' | 'testTarget' | 'upsertTarget' | 'deleteTarget' | 'setTargetEnabled'>;
79
+ readonly notificationRules: Pick<InferProvider<typeof notificationRulesCapability>, 'listRules' | 'getRule' | 'createRule' | 'updateRule' | 'deleteRule' | 'setRuleEnabled' | 'testRule' | 'getConditionCatalog'>;
78
80
  readonly pipelineExecutor: Pick<InferProvider<typeof pipelineExecutorCapability>, 'getAvailableEngines' | 'getSelectedEngine' | 'getDefaultSteps' | 'getEngineProvisioning' | 'getVideoPipelineSteps' | 'setVideoPipelineSteps' | 'clearDeviceOverrides' | 'getSchema' | 'getGlobalSteps' | 'getGlobalPipelineConfig' | 'getOrchestratorConfigSchema' | 'validatePipeline' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate' | 'getCapabilities' | 'getAddonModels' | 'downloadModel' | 'deleteModel' | 'cacheFrameInPool' | 'inferCached' | 'uncacheFrame' | 'getEffectiveTuning' | 'listLoadedEngines' | 'spinEngine' | 'killEngine' | 'listReferenceImages' | 'getReferenceImage' | 'getReferenceAudioFiles' | 'getReferenceAudio' | 'getAudioCapabilities' | 'runAudioTest' | 'getDetectionConfigSchema'>;
79
81
  readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getIngestOwner' | 'getAudioNodeLoad' | 'getAgentSettings' | 'listAgentSettings' | 'removeAgentSettings' | 'setAgentMaxCameras' | 'setAgentDetectWeight' | 'setAgentCapabilities' | 'setAgentReachableHost' | 'setAgentInferenceDevices' | 'getNodeInferenceDevices' | 'resetNodePipelineDefaults' | 'getCameraStatuses' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>;
80
82
  readonly pipelineRunner: Pick<InferProvider<typeof pipelineRunnerCapability>, 'attachCamera' | 'reportMotion' | 'getLocalLoad' | 'getLocalMetrics' | 'getAllCameraMetrics' | 'getLocalCameras' | 'getNativeCrop'>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-eVjOy4ev.js");
2
+ const require_sleep = require("./sleep-D1IRluEi.js");
3
3
  const require_event_category = require("./event-category-CGj9fI4L.js");
4
4
  const require_enums = require("./enums.js");
5
5
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -13575,6 +13575,16 @@ function createSystemProxy(api) {
13575
13575
  deleteTarget: (input) => dispatch("notificationOutput", "deleteTarget", "mutation", input),
13576
13576
  setTargetEnabled: (input) => dispatch("notificationOutput", "setTargetEnabled", "mutation", input)
13577
13577
  },
13578
+ notificationRules: {
13579
+ listRules: (input) => dispatch("notificationRules", "listRules", "query", input),
13580
+ getRule: (input) => dispatch("notificationRules", "getRule", "query", input),
13581
+ createRule: (input) => dispatch("notificationRules", "createRule", "mutation", input),
13582
+ updateRule: (input) => dispatch("notificationRules", "updateRule", "mutation", input),
13583
+ deleteRule: (input) => dispatch("notificationRules", "deleteRule", "mutation", input),
13584
+ setRuleEnabled: (input) => dispatch("notificationRules", "setRuleEnabled", "mutation", input),
13585
+ testRule: (input) => dispatch("notificationRules", "testRule", "mutation", input),
13586
+ getConditionCatalog: (input) => dispatch("notificationRules", "getConditionCatalog", "query", input)
13587
+ },
13578
13588
  pipelineExecutor: {
13579
13589
  getAvailableEngines: (input) => dispatch("pipelineExecutor", "getAvailableEngines", "query", input),
13580
13590
  getSelectedEngine: (input) => dispatch("pipelineExecutor", "getSelectedEngine", "query", input),
@@ -18372,6 +18382,358 @@ var notificationOutputCapability = {
18372
18382
  }
18373
18383
  };
18374
18384
  //#endregion
18385
+ //#region src/capabilities/notification-rules.cap.ts
18386
+ /**
18387
+ * notification-rules — the Notification Center rule surface (P1 core).
18388
+ *
18389
+ * Spec: `docs/superpowers/specs/2026-07-22-notification-center-requirements.md`
18390
+ * (operator decisions D-1/D-2/D-3 are binding):
18391
+ *
18392
+ * - D-2: rule EVALUATION lives in `addon-post-analysis` (the
18393
+ * `notification-center` module), hooked on the durable persistence
18394
+ * moments (object-event insert, TrackCloser.closeExpired) with a
18395
+ * persisted outbox + retry — never the lossy telemetry bus (D8).
18396
+ * - D-3: urgency belongs to the RULE. `delivery: 'immediate'` fires on the
18397
+ * FIRST persisted detection matching the conditions (per-track dedup,
18398
+ * `maxPerTrack` fixed at 1 — see {@link NC_MAX_PER_TRACK_IMMEDIATE});
18399
+ * `delivery: 'track-end'` evaluates the finalized track record at close.
18400
+ * - DISPATCH stays behind `notification-output` (rules reference targets
18401
+ * by id; per-backend params are a passthrough blob capped by the
18402
+ * target kind's own caps/degrade engine).
18403
+ *
18404
+ * P1 scope: admin-authored rules only (`createdBy` stamped from the
18405
+ * server-injected caller identity — the first `caller: 'required'`
18406
+ * adopter). The P1 condition subset is: devices, classes(+exclude),
18407
+ * minConfidence, admin zones (any/all + exclude), weekly schedule
18408
+ * windows, and the optional label/identity/plate matchers. User rules,
18409
+ * private zones, per-recipient fan-out and the wider condition table are
18410
+ * P2+ (see spec §7).
18411
+ *
18412
+ * All schemas here are the single source of truth — `NcRule` etc. are
18413
+ * `z.infer` exports; no duplicate interfaces (the advanced-notifier
18414
+ * schema/interface drift is explicitly not repeated).
18415
+ */
18416
+ /** D-3: the urgency of a rule — which persistence moment evaluates it. */
18417
+ var NcDeliverySchema = zod.z.enum(["immediate", "track-end"]);
18418
+ /**
18419
+ * `maxPerTrack` for `immediate` rules is FIXED at 1 (D-3): a single track
18420
+ * fires an immediate rule at most once, enforced durably by the outbox
18421
+ * unique key `(ruleId, trackId, targetId)`. Not a rule field in P1.
18422
+ */
18423
+ var NC_MAX_PER_TRACK_IMMEDIATE = 1;
18424
+ /** One weekly activation window. `startMinute > endMinute` crosses midnight. */
18425
+ var NcScheduleWindowSchema = zod.z.object({
18426
+ /** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
18427
+ days: zod.z.array(zod.z.number().int().min(0).max(6)).min(1),
18428
+ startMinute: zod.z.number().int().min(0).max(1439),
18429
+ endMinute: zod.z.number().int().min(0).max(1439)
18430
+ });
18431
+ /** Weekly schedule — OR of windows; absence on the rule = always active. */
18432
+ var NcScheduleSchema = zod.z.object({
18433
+ windows: zod.z.array(NcScheduleWindowSchema).min(1),
18434
+ /** IANA timezone; default = hub host timezone. */
18435
+ timezone: zod.z.string().optional(),
18436
+ /** Active OUTSIDE the windows (e.g. "only outside business hours"). */
18437
+ invert: zod.z.boolean().optional()
18438
+ });
18439
+ /** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
18440
+ var NcPlateMatcherSchema = zod.z.object({
18441
+ values: zod.z.array(zod.z.string().min(1)).min(1),
18442
+ /** Max Levenshtein distance after normalization (uppercase alphanumeric). */
18443
+ maxDistance: zod.z.number().int().min(0).max(3).default(1)
18444
+ });
18445
+ /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
18446
+ var NcZoneConditionSchema = zod.z.object({
18447
+ ids: zod.z.array(zod.z.string().min(1)).min(1),
18448
+ /** Quantifier over `ids` — at least one / every one visited. */
18449
+ match: zod.z.enum(["any", "all"]).default("any")
18450
+ });
18451
+ /**
18452
+ * The P1 condition set — a flat AND of groups; absent group = pass;
18453
+ * membership lists are OR within the list (spec §2.3).
18454
+ */
18455
+ var NcConditionsSchema = zod.z.object({
18456
+ /** Device scope — absent = all devices. */
18457
+ devices: zod.z.array(zod.z.number()).optional(),
18458
+ /** Detector class names (any overlap with the record's class set). */
18459
+ classes: zod.z.array(zod.z.string().min(1)).optional(),
18460
+ /** Veto classes — any overlap fails the rule. */
18461
+ classesExclude: zod.z.array(zod.z.string().min(1)).optional(),
18462
+ /** Minimum detection confidence 0–1 (fails when the record has none). */
18463
+ minConfidence: zod.z.number().min(0).max(1).optional(),
18464
+ /** Admin zone membership over event `zones` / track `zonesVisited`. */
18465
+ zones: NcZoneConditionSchema.optional(),
18466
+ /** Veto zones — any hit fails the rule. */
18467
+ zonesExclude: zod.z.array(zod.z.string().min(1)).optional(),
18468
+ /**
18469
+ * Exact (case-insensitive) match on the record's collapsed `label`
18470
+ * (identity name / plate text / subclass).
18471
+ */
18472
+ labelEquals: zod.z.array(zod.z.string().min(1)).optional(),
18473
+ /**
18474
+ * Identity matcher. P1 boundary: matched against the record's collapsed
18475
+ * `label` (the identity display name propagated by the face pipeline) —
18476
+ * identity-ID matching rides in P2 when identity ids reach the record.
18477
+ */
18478
+ identities: zod.z.array(zod.z.string().min(1)).optional(),
18479
+ /** Fuzzy plate matcher against the record's `label` (plate text). */
18480
+ plates: NcPlateMatcherSchema.optional()
18481
+ });
18482
+ /** One delivery target: a `notification-output` Target ref + passthrough params. */
18483
+ var NcRuleTargetSchema = zod.z.object({
18484
+ /** `notification-output` Target id. */
18485
+ targetId: zod.z.string().min(1),
18486
+ /**
18487
+ * Per-backend passthrough. Recognized keys are mapped onto the canonical
18488
+ * Notification (`priority`, `level`, `sound`, `clickUrl`, `ttl`); the
18489
+ * degrade engine drops what the backend can't render.
18490
+ */
18491
+ params: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
18492
+ });
18493
+ /**
18494
+ * Media attachment policy (P1 still-image subset). `best` = the best
18495
+ * AVAILABLE media at dispatch time (D-3); `best-matching` (track-end
18496
+ * condition-best) is deferred — operator open point.
18497
+ */
18498
+ var NcMediaPolicySchema = zod.z.object({ attach: zod.z.enum([
18499
+ "best",
18500
+ "keyFrame",
18501
+ "none"
18502
+ ]).default("best") });
18503
+ /** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
18504
+ var NcThrottleSchema = zod.z.object({
18505
+ cooldownSec: zod.z.number().int().min(0).max(86400).default(60),
18506
+ /** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
18507
+ scope: zod.z.enum(["rule", "rule-device"]).default("rule-device")
18508
+ });
18509
+ /** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
18510
+ var NcRuleInputSchema = zod.z.object({
18511
+ name: zod.z.string().min(1).max(200),
18512
+ enabled: zod.z.boolean().default(true),
18513
+ delivery: NcDeliverySchema,
18514
+ conditions: NcConditionsSchema.default({}),
18515
+ schedule: NcScheduleSchema.optional(),
18516
+ targets: zod.z.array(NcRuleTargetSchema).min(1),
18517
+ media: NcMediaPolicySchema.default({ attach: "best" }),
18518
+ throttle: NcThrottleSchema.default({
18519
+ cooldownSec: 60,
18520
+ scope: "rule-device"
18521
+ }),
18522
+ /** `{{var}}` templating over camera/class/label/zones/confidence/time. */
18523
+ template: zod.z.object({
18524
+ title: zod.z.string().max(500).optional(),
18525
+ body: zod.z.string().max(2e3).optional()
18526
+ }).optional(),
18527
+ /** Canonical notification priority ordinal (1..5); per-target overridable. */
18528
+ priority: zod.z.number().int().min(1).max(5).default(3)
18529
+ });
18530
+ /** Partial patch for `updateRule` — any subset of the input fields. */
18531
+ var NcRulePatchSchema = NcRuleInputSchema.partial();
18532
+ /** A persisted rule. */
18533
+ var NcRuleSchema = NcRuleInputSchema.extend({
18534
+ id: zod.z.string(),
18535
+ /** userId of the admin who created the rule (server-stamped caller). */
18536
+ createdBy: zod.z.string(),
18537
+ createdAt: zod.z.number(),
18538
+ updatedAt: zod.z.number()
18539
+ });
18540
+ var NcTestResultSchema = zod.z.object({
18541
+ recordId: zod.z.string(),
18542
+ recordKind: zod.z.enum(["object-event", "track"]),
18543
+ deviceId: zod.z.number(),
18544
+ timestamp: zod.z.number(),
18545
+ wouldFire: zod.z.boolean(),
18546
+ /** Condition id that failed (first failing group), when `wouldFire` is false. */
18547
+ failedCondition: zod.z.string().optional(),
18548
+ className: zod.z.string().optional(),
18549
+ label: zod.z.string().optional()
18550
+ });
18551
+ var NcConditionDescriptorSchema = zod.z.object({
18552
+ /** Field id inside `NcConditions` (or `'schedule'` for the rule-level group). */
18553
+ id: zod.z.string(),
18554
+ group: zod.z.enum([
18555
+ "scope",
18556
+ "class",
18557
+ "zones",
18558
+ "quality",
18559
+ "label",
18560
+ "schedule"
18561
+ ]),
18562
+ label: zod.z.string(),
18563
+ /** Editor widget the UI renders — never hardcode per-condition forms. */
18564
+ valueType: zod.z.enum([
18565
+ "deviceIdList",
18566
+ "stringList",
18567
+ "number01",
18568
+ "zoneSelection",
18569
+ "zoneIdList",
18570
+ "schedule",
18571
+ "plateMatcher"
18572
+ ]),
18573
+ operator: zod.z.enum([
18574
+ "in",
18575
+ "notIn",
18576
+ "anyOf",
18577
+ "allOf",
18578
+ "gte",
18579
+ "fuzzyIn",
18580
+ "withinSchedule"
18581
+ ]),
18582
+ /** Which delivery kinds the condition applies to. */
18583
+ appliesTo: zod.z.array(NcDeliverySchema),
18584
+ phase: zod.z.string(),
18585
+ description: zod.z.string().optional()
18586
+ });
18587
+ /**
18588
+ * The P1 condition surface as data — served by `getConditionCatalog` so
18589
+ * rule editors render from the catalog, not hardcoded forms (spec §4.2).
18590
+ */
18591
+ var NC_CONDITION_CATALOG = [
18592
+ {
18593
+ id: "devices",
18594
+ group: "scope",
18595
+ label: "Cameras",
18596
+ valueType: "deviceIdList",
18597
+ operator: "in",
18598
+ appliesTo: ["immediate", "track-end"],
18599
+ phase: "P1",
18600
+ description: "Restrict the rule to these devices; absent = all devices."
18601
+ },
18602
+ {
18603
+ id: "classes",
18604
+ group: "class",
18605
+ label: "Object classes",
18606
+ valueType: "stringList",
18607
+ operator: "in",
18608
+ appliesTo: ["immediate", "track-end"],
18609
+ phase: "P1",
18610
+ description: "Any overlap with the detection class set passes."
18611
+ },
18612
+ {
18613
+ id: "classesExclude",
18614
+ group: "class",
18615
+ label: "Excluded classes",
18616
+ valueType: "stringList",
18617
+ operator: "notIn",
18618
+ appliesTo: ["immediate", "track-end"],
18619
+ phase: "P1"
18620
+ },
18621
+ {
18622
+ id: "minConfidence",
18623
+ group: "quality",
18624
+ label: "Minimum confidence",
18625
+ valueType: "number01",
18626
+ operator: "gte",
18627
+ appliesTo: ["immediate", "track-end"],
18628
+ phase: "P1"
18629
+ },
18630
+ {
18631
+ id: "zones",
18632
+ group: "zones",
18633
+ label: "Zones",
18634
+ valueType: "zoneSelection",
18635
+ operator: "anyOf",
18636
+ appliesTo: ["immediate", "track-end"],
18637
+ phase: "P1",
18638
+ description: "Admin zone ids; quantifier any/all over the visited set."
18639
+ },
18640
+ {
18641
+ id: "zonesExclude",
18642
+ group: "zones",
18643
+ label: "Excluded zones",
18644
+ valueType: "zoneIdList",
18645
+ operator: "notIn",
18646
+ appliesTo: ["immediate", "track-end"],
18647
+ phase: "P1"
18648
+ },
18649
+ {
18650
+ id: "labelEquals",
18651
+ group: "label",
18652
+ label: "Label equals",
18653
+ valueType: "stringList",
18654
+ operator: "in",
18655
+ appliesTo: ["immediate", "track-end"],
18656
+ phase: "P1",
18657
+ description: "Exact match on the collapsed label (identity / plate / subclass)."
18658
+ },
18659
+ {
18660
+ id: "identities",
18661
+ group: "label",
18662
+ label: "Identities",
18663
+ valueType: "stringList",
18664
+ operator: "in",
18665
+ appliesTo: ["immediate", "track-end"],
18666
+ phase: "P1",
18667
+ description: "P1: matched against the identity display name on the record label."
18668
+ },
18669
+ {
18670
+ id: "plates",
18671
+ group: "label",
18672
+ label: "License plates",
18673
+ valueType: "plateMatcher",
18674
+ operator: "fuzzyIn",
18675
+ appliesTo: ["immediate", "track-end"],
18676
+ phase: "P1",
18677
+ description: "Levenshtein-tolerant match against the plate text."
18678
+ },
18679
+ {
18680
+ id: "schedule",
18681
+ group: "schedule",
18682
+ label: "Schedule",
18683
+ valueType: "schedule",
18684
+ operator: "withinSchedule",
18685
+ appliesTo: ["immediate", "track-end"],
18686
+ phase: "P1",
18687
+ description: "Weekly activation windows (invertible); absent = always active."
18688
+ }
18689
+ ];
18690
+ var notificationRulesCapability = {
18691
+ name: "notification-rules",
18692
+ scope: "system",
18693
+ mode: "singleton",
18694
+ methods: {
18695
+ listRules: require_sleep.method(zod.z.object({}), zod.z.object({ rules: zod.z.array(NcRuleSchema) }), { auth: "admin" }),
18696
+ getRule: require_sleep.method(zod.z.object({ ruleId: zod.z.string() }), zod.z.object({ rule: NcRuleSchema.nullable() }), { auth: "admin" }),
18697
+ createRule: require_sleep.method(zod.z.object({ rule: NcRuleInputSchema }), zod.z.object({ rule: NcRuleSchema }), {
18698
+ kind: "mutation",
18699
+ auth: "admin",
18700
+ caller: "required"
18701
+ }),
18702
+ updateRule: require_sleep.method(zod.z.object({
18703
+ ruleId: zod.z.string(),
18704
+ patch: NcRulePatchSchema
18705
+ }), zod.z.object({ rule: NcRuleSchema }), {
18706
+ kind: "mutation",
18707
+ auth: "admin",
18708
+ caller: "required"
18709
+ }),
18710
+ deleteRule: require_sleep.method(zod.z.object({ ruleId: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
18711
+ kind: "mutation",
18712
+ auth: "admin"
18713
+ }),
18714
+ setRuleEnabled: require_sleep.method(zod.z.object({
18715
+ ruleId: zod.z.string(),
18716
+ enabled: zod.z.boolean()
18717
+ }), zod.z.object({ success: zod.z.literal(true) }), {
18718
+ kind: "mutation",
18719
+ auth: "admin"
18720
+ }),
18721
+ /**
18722
+ * Dry-run a rule against recently persisted records (object events for
18723
+ * `immediate`, closed tracks for `track-end`). Mutation kind only to
18724
+ * carry the full rule object safely; no side effects.
18725
+ */
18726
+ testRule: require_sleep.method(zod.z.object({
18727
+ rule: NcRuleInputSchema,
18728
+ lookbackMinutes: zod.z.number().int().min(1).max(1440).default(60)
18729
+ }), zod.z.object({ results: zod.z.array(NcTestResultSchema) }), {
18730
+ kind: "mutation",
18731
+ auth: "admin"
18732
+ }),
18733
+ getConditionCatalog: require_sleep.method(zod.z.object({}), zod.z.object({ catalog: zod.z.array(NcConditionDescriptorSchema) }))
18734
+ }
18735
+ };
18736
+ //#endregion
18375
18737
  //#region src/capabilities/llm-shared.ts
18376
18738
  /**
18377
18739
  * Shared LLM generate contracts — imported by BOTH `llm.cap.ts` (consumer
@@ -25360,6 +25722,7 @@ var CAPABILITY_NAMES = {
25360
25722
  networkQuality: "network-quality",
25361
25723
  nodes: "nodes",
25362
25724
  notificationOutput: "notification-output",
25725
+ notificationRules: "notification-rules",
25363
25726
  notifier: "notifier",
25364
25727
  numericSensor: "numeric-sensor",
25365
25728
  oauthIntegration: "oauth-integration",
@@ -25769,6 +26132,10 @@ var CAPABILITY_ROUTER_KEYS = [
25769
26132
  key: "notificationOutput",
25770
26133
  name: "notification-output"
25771
26134
  },
26135
+ {
26136
+ key: "notificationRules",
26137
+ name: "notification-rules"
26138
+ },
25772
26139
  {
25773
26140
  key: "notifier",
25774
26141
  name: "notifier"
@@ -26084,6 +26451,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
26084
26451
  networkQualityCapability,
26085
26452
  nodesCapability,
26086
26453
  notificationOutputCapability,
26454
+ notificationRulesCapability,
26087
26455
  notifierCapability,
26088
26456
  numericSensorCapability,
26089
26457
  oauthIntegrationCapability,
@@ -28829,6 +29197,54 @@ var METHOD_ACCESS_MAP = Object.freeze({
28829
29197
  addonId: null,
28830
29198
  access: "create"
28831
29199
  },
29200
+ "notificationRules.createRule": {
29201
+ capName: "notification-rules",
29202
+ capScope: "system",
29203
+ addonId: null,
29204
+ access: "create"
29205
+ },
29206
+ "notificationRules.deleteRule": {
29207
+ capName: "notification-rules",
29208
+ capScope: "system",
29209
+ addonId: null,
29210
+ access: "delete"
29211
+ },
29212
+ "notificationRules.getConditionCatalog": {
29213
+ capName: "notification-rules",
29214
+ capScope: "system",
29215
+ addonId: null,
29216
+ access: "view"
29217
+ },
29218
+ "notificationRules.getRule": {
29219
+ capName: "notification-rules",
29220
+ capScope: "system",
29221
+ addonId: null,
29222
+ access: "view"
29223
+ },
29224
+ "notificationRules.listRules": {
29225
+ capName: "notification-rules",
29226
+ capScope: "system",
29227
+ addonId: null,
29228
+ access: "view"
29229
+ },
29230
+ "notificationRules.setRuleEnabled": {
29231
+ capName: "notification-rules",
29232
+ capScope: "system",
29233
+ addonId: null,
29234
+ access: "create"
29235
+ },
29236
+ "notificationRules.testRule": {
29237
+ capName: "notification-rules",
29238
+ capScope: "system",
29239
+ addonId: null,
29240
+ access: "create"
29241
+ },
29242
+ "notificationRules.updateRule": {
29243
+ capName: "notification-rules",
29244
+ capScope: "system",
29245
+ addonId: null,
29246
+ access: "create"
29247
+ },
28832
29248
  "notifier.cancel": {
28833
29249
  capName: "notifier",
28834
29250
  capScope: "device",
@@ -31105,6 +31521,7 @@ var KNOWN_CAP_NAMES = [
31105
31521
  "network-quality",
31106
31522
  "nodes",
31107
31523
  "notification-output",
31524
+ "notification-rules",
31108
31525
  "notifier",
31109
31526
  "oauth-integration",
31110
31527
  "osd",
@@ -31250,6 +31667,7 @@ var SYSTEM_CAP_NAMES = [
31250
31667
  "network-quality",
31251
31668
  "nodes",
31252
31669
  "notification-output",
31670
+ "notification-rules",
31253
31671
  "oauth-integration",
31254
31672
  "pipeline-executor",
31255
31673
  "pipeline-orchestrator",
@@ -32229,6 +32647,8 @@ exports.MotionZonePatchSchema = MotionZonePatchSchema;
32229
32647
  exports.MotionZoneRegionSchema = MotionZoneRegionSchema;
32230
32648
  exports.MotionZoneStatusSchema = MotionZoneStatusSchema;
32231
32649
  exports.MqttBrokerStatusSchema = StatusSchema;
32650
+ exports.NC_CONDITION_CATALOG = NC_CONDITION_CATALOG;
32651
+ exports.NC_MAX_PER_TRACK_IMMEDIATE = NC_MAX_PER_TRACK_IMMEDIATE;
32232
32652
  exports.NativeCropBboxSchema = NativeCropBboxSchema;
32233
32653
  exports.NativeCropRefSchema = NativeCropRefSchema;
32234
32654
  exports.NativeCropResultSchema = NativeCropResultSchema;
@@ -32236,6 +32656,20 @@ exports.NativeDetectionSchema = NativeDetectionSchema;
32236
32656
  exports.NativeObjectClassEnum = NativeObjectClassEnum;
32237
32657
  exports.NativeObjectDetectionRuntimeStateSchema = NativeObjectDetectionRuntimeStateSchema;
32238
32658
  exports.NativeObjectDetectionStatusSchema = NativeObjectDetectionStatusSchema;
32659
+ exports.NcConditionDescriptorSchema = NcConditionDescriptorSchema;
32660
+ exports.NcConditionsSchema = NcConditionsSchema;
32661
+ exports.NcDeliverySchema = NcDeliverySchema;
32662
+ exports.NcMediaPolicySchema = NcMediaPolicySchema;
32663
+ exports.NcPlateMatcherSchema = NcPlateMatcherSchema;
32664
+ exports.NcRuleInputSchema = NcRuleInputSchema;
32665
+ exports.NcRulePatchSchema = NcRulePatchSchema;
32666
+ exports.NcRuleSchema = NcRuleSchema;
32667
+ exports.NcRuleTargetSchema = NcRuleTargetSchema;
32668
+ exports.NcScheduleSchema = NcScheduleSchema;
32669
+ exports.NcScheduleWindowSchema = NcScheduleWindowSchema;
32670
+ exports.NcTestResultSchema = NcTestResultSchema;
32671
+ exports.NcThrottleSchema = NcThrottleSchema;
32672
+ exports.NcZoneConditionSchema = NcZoneConditionSchema;
32239
32673
  exports.NetworkAccessStatusSchema = NetworkAccessStatusSchema;
32240
32674
  exports.NetworkAddressSchema = NetworkAddressSchema;
32241
32675
  exports.NetworkEndpointSchema = NetworkEndpointSchema;
@@ -32672,6 +33106,7 @@ exports.nodesCapability = nodesCapability;
32672
33106
  exports.normalizeAddonInitResult = require_sleep.normalizeAddonInitResult;
32673
33107
  exports.normalizeUnit = normalizeUnit;
32674
33108
  exports.notificationOutputCapability = notificationOutputCapability;
33109
+ exports.notificationRulesCapability = notificationRulesCapability;
32675
33110
  exports.notifierCapability = notifierCapability;
32676
33111
  exports.numericSensorCapability = numericSensorCapability;
32677
33112
  exports.oauthIntegrationCapability = oauthIntegrationCapability;