@camstack/addon-post-analysis 1.2.34 → 1.2.35

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.
@@ -9454,6 +9454,100 @@ function shallowEqual(a, b) {
9454
9454
  }
9455
9455
  new Set(["devices", "classes"]);
9456
9456
  /**
9457
+ * Alarm-panel cap. Models HA `alarm_control_panel.*` on
9458
+ * `DeviceType.AlarmPanel`. State follows HA's canonical lifecycle
9459
+ * across disarmed / armed_(home|away|night|vacation|custom_bypass) /
9460
+ * arming / pending / triggered / disarming.
9461
+ *
9462
+ * Many panels require a PIN code on arm / disarm — the optional
9463
+ * `code` field on the methods passes it through to the upstream
9464
+ * service; it's NEVER persisted in the runtime slice or any event
9465
+ * payload. The presence of a required code is signalled by
9466
+ * `DeviceFeature.AlarmPinRequired` so the UI gates a code-entry
9467
+ * field without a slice fetch.
9468
+ *
9469
+ * `availableModes` mirrors HA's `supported_features`-derived arm
9470
+ * mode list — the UI renders only the buttons the panel accepts.
9471
+ */
9472
+ var AlarmStateSchema = _enum([
9473
+ "disarmed",
9474
+ "armed_home",
9475
+ "armed_away",
9476
+ "armed_night",
9477
+ "armed_vacation",
9478
+ "armed_custom_bypass",
9479
+ "arming",
9480
+ "disarming",
9481
+ "pending",
9482
+ "triggered"
9483
+ ]);
9484
+ var AlarmArmModeSchema = _enum([
9485
+ "home",
9486
+ "away",
9487
+ "night",
9488
+ "vacation",
9489
+ "custom_bypass"
9490
+ ]);
9491
+ var AlarmPanelStatusSchema = object({
9492
+ /** Current lifecycle state. */
9493
+ state: AlarmStateSchema,
9494
+ /** Subset of arm modes the panel accepts. UI renders one button per
9495
+ * mode in this list. */
9496
+ availableModes: array(AlarmArmModeSchema),
9497
+ /** Whether the panel requires a PIN on arm / disarm. Mirrors
9498
+ * `DeviceFeature.AlarmPinRequired` for slice consumers. */
9499
+ requiresCode: boolean(),
9500
+ /** Ms epoch when the slice was last updated. */
9501
+ lastChangedAt: number()
9502
+ });
9503
+ var alarmPanelCapability = {
9504
+ name: "alarm-panel",
9505
+ scope: "device",
9506
+ deviceNative: true,
9507
+ mode: "singleton",
9508
+ deviceTypes: [DeviceType.AlarmPanel],
9509
+ methods: {
9510
+ arm: method(object({
9511
+ deviceId: number().int().nonnegative(),
9512
+ mode: AlarmArmModeSchema,
9513
+ /** Optional PIN code. Required when `requiresCode === true`.
9514
+ * Passed through to the upstream service; never persisted. */
9515
+ code: string().min(1).optional()
9516
+ }), _void(), {
9517
+ kind: "mutation",
9518
+ auth: "admin"
9519
+ }),
9520
+ disarm: method(object({
9521
+ deviceId: number().int().nonnegative(),
9522
+ code: string().min(1).optional()
9523
+ }), _void(), {
9524
+ kind: "mutation",
9525
+ auth: "admin"
9526
+ }),
9527
+ /**
9528
+ * Force the panel into the `triggered` state — used by HA
9529
+ * automations to surface external sensor events through the panel
9530
+ * (e.g. a Reolink camera intrusion event firing the security
9531
+ * system). Provider rejects when the panel hardware doesn't
9532
+ * support a software-initiated trigger.
9533
+ */
9534
+ trigger: method(object({ deviceId: number().int().nonnegative() }), _void(), {
9535
+ kind: "mutation",
9536
+ auth: "admin"
9537
+ })
9538
+ },
9539
+ status: {
9540
+ schema: AlarmPanelStatusSchema,
9541
+ kind: "push"
9542
+ },
9543
+ /**
9544
+ * Runtime-state slice — mirrored by the kernel. UI panel reads the
9545
+ * full slice; renders an arm button per `availableModes` entry and
9546
+ * a PIN field iff `requiresCode === true`.
9547
+ */
9548
+ runtimeState: AlarmPanelStatusSchema
9549
+ };
9550
+ /**
9457
9551
  * Shared geometry vocabulary for on-frame shape caps — privacy-mask,
9458
9552
  * motion-zones, and the detection zones/lines editor all speak this one
9459
9553
  * language so a single drawing-plane editor and the providers stay
@@ -10442,7 +10536,7 @@ var NC_CONDITION_CATALOG = [
10442
10536
  {
10443
10537
  id: "devices",
10444
10538
  group: "scope",
10445
- label: "Cameras",
10539
+ label: "Devices",
10446
10540
  valueType: "deviceIdList",
10447
10541
  operator: "in",
10448
10542
  appliesTo: [
@@ -10452,7 +10546,7 @@ var NC_CONDITION_CATALOG = [
10452
10546
  "package-event"
10453
10547
  ],
10454
10548
  phase: "P1",
10455
- description: "Restrict the rule to these devices; absent = all devices."
10549
+ description: "Restrict the rule to these devices; absent = all devices. A sensor event matches either the SENSOR that fired or the camera it is attributed to, so a rule may name either one."
10456
10550
  },
10457
10551
  {
10458
10552
  id: "classes",
@@ -10907,6 +11001,67 @@ var NcSnoozeSuppressedSchema = object({
10907
11001
  firstAt: number(),
10908
11002
  lastAt: number()
10909
11003
  });
11004
+ /**
11005
+ * The three durations the panel's state machine runs on, plus who hears about
11006
+ * an arm.
11007
+ *
11008
+ * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
11009
+ * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
11010
+ * else's panel, which has its own delays and no way to be told these. This is
11011
+ * configuration of the panel CamStack owns, and the Notification Center owns
11012
+ * that panel.
11013
+ */
11014
+ var NcAlarmSettingsSchema = object({
11015
+ /** Grace period between arming and the mode taking effect. 0 = immediate. */
11016
+ exitDelaySec: number().int().min(0).max(600),
11017
+ /** Grace period between a trigger and the alarm firing. 0 = immediate. */
11018
+ entryDelaySec: number().int().min(0).max(600),
11019
+ /**
11020
+ * How long `triggered` lasts before the panel re-arms itself.
11021
+ * **0 = until an operator disarms it** — the behaviour before this field
11022
+ * existed, and therefore what an untouched install keeps doing.
11023
+ */
11024
+ triggeredDurationSec: number().int().min(0).max(3600),
11025
+ /** Send a notification when a mode takes effect. */
11026
+ announceArm: boolean(),
11027
+ /**
11028
+ * Where that notification goes. Target ids from `notification-output`.
11029
+ *
11030
+ * Explicit rather than "everyone": an arm announcement is a household
11031
+ * message, and broadcasting it to every configured endpoint (including a
11032
+ * webhook wired to something else) is not a default anybody would choose.
11033
+ * Empty with `announceArm: true` sends nothing, and the server logs that —
11034
+ * silence must be attributable.
11035
+ */
11036
+ announceTargets: array(string().min(1)).max(16)
11037
+ });
11038
+ /** Every field optional — a tab edits one control at a time. */
11039
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.partial();
11040
+ /**
11041
+ * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
11042
+ * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
11043
+ * copy would lie the first time a rule is disabled.
11044
+ */
11045
+ var NcAlarmModeCoverageSchema = object({
11046
+ mode: AlarmArmModeSchema,
11047
+ /** Enabled rules gated on `armed_<mode>`. Zero means the mode does nothing. */
11048
+ ruleCount: number().int().min(0),
11049
+ /** At least one covering rule has no device scope, so the mode covers all. */
11050
+ allDevices: boolean(),
11051
+ /** Ids named by the covering rules. A SUBSET when `allDevices` is true. */
11052
+ deviceIds: array(number().int())
11053
+ });
11054
+ var NcAlarmConfigSchema = object({
11055
+ /**
11056
+ * The panel's device id, or null when this install has no panel (the ensure
11057
+ * step failed, or this is not the hub). Null is the honest answer: an editor
11058
+ * that rendered delays for a panel that does not exist would be a form whose
11059
+ * Save does nothing.
11060
+ */
11061
+ deviceId: number().int().nullable(),
11062
+ settings: NcAlarmSettingsSchema,
11063
+ coverage: array(NcAlarmModeCoverageSchema)
11064
+ });
10910
11065
  var notificationRulesCapability = {
10911
11066
  name: "notification-rules",
10912
11067
  scope: "system",
@@ -11002,6 +11157,26 @@ var notificationRulesCapability = {
11002
11157
  cancelSnooze: method(object({ snoozeId: string() }), object({ success: literal(true) }), {
11003
11158
  kind: "mutation",
11004
11159
  caller: "required"
11160
+ }),
11161
+ /**
11162
+ * The alarm panel's durations, plus what each mode ACTUALLY arms.
11163
+ *
11164
+ * Coverage is returned by the same call as the settings on purpose: they
11165
+ * are read together or not at all. An editor that showed the delays
11166
+ * without the coverage would let an operator tune an exit delay for a mode
11167
+ * that arms nothing, which is the failure this whole surface exists to
11168
+ * make visible.
11169
+ */
11170
+ getAlarmConfig: method(object({}), NcAlarmConfigSchema, { auth: "admin" }),
11171
+ /**
11172
+ * Patch the durations. Returns the WHOLE config, coverage included, so a
11173
+ * client never has to guess what the server settled on — the panel clamps
11174
+ * and normalises, and a form that re-rendered from its own input would
11175
+ * show a value the alarm is not using.
11176
+ */
11177
+ setAlarmConfig: method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
11178
+ kind: "mutation",
11179
+ auth: "admin"
11005
11180
  })
11006
11181
  }
11007
11182
  };
@@ -11265,100 +11440,6 @@ var airQualitySensorCapability = {
11265
11440
  runtimeState: AirQualitySensorStatusSchema
11266
11441
  };
11267
11442
  /**
11268
- * Alarm-panel cap. Models HA `alarm_control_panel.*` on
11269
- * `DeviceType.AlarmPanel`. State follows HA's canonical lifecycle
11270
- * across disarmed / armed_(home|away|night|vacation|custom_bypass) /
11271
- * arming / pending / triggered / disarming.
11272
- *
11273
- * Many panels require a PIN code on arm / disarm — the optional
11274
- * `code` field on the methods passes it through to the upstream
11275
- * service; it's NEVER persisted in the runtime slice or any event
11276
- * payload. The presence of a required code is signalled by
11277
- * `DeviceFeature.AlarmPinRequired` so the UI gates a code-entry
11278
- * field without a slice fetch.
11279
- *
11280
- * `availableModes` mirrors HA's `supported_features`-derived arm
11281
- * mode list — the UI renders only the buttons the panel accepts.
11282
- */
11283
- var AlarmStateSchema = _enum([
11284
- "disarmed",
11285
- "armed_home",
11286
- "armed_away",
11287
- "armed_night",
11288
- "armed_vacation",
11289
- "armed_custom_bypass",
11290
- "arming",
11291
- "disarming",
11292
- "pending",
11293
- "triggered"
11294
- ]);
11295
- var AlarmArmModeSchema = _enum([
11296
- "home",
11297
- "away",
11298
- "night",
11299
- "vacation",
11300
- "custom_bypass"
11301
- ]);
11302
- var AlarmPanelStatusSchema = object({
11303
- /** Current lifecycle state. */
11304
- state: AlarmStateSchema,
11305
- /** Subset of arm modes the panel accepts. UI renders one button per
11306
- * mode in this list. */
11307
- availableModes: array(AlarmArmModeSchema),
11308
- /** Whether the panel requires a PIN on arm / disarm. Mirrors
11309
- * `DeviceFeature.AlarmPinRequired` for slice consumers. */
11310
- requiresCode: boolean(),
11311
- /** Ms epoch when the slice was last updated. */
11312
- lastChangedAt: number()
11313
- });
11314
- var alarmPanelCapability = {
11315
- name: "alarm-panel",
11316
- scope: "device",
11317
- deviceNative: true,
11318
- mode: "singleton",
11319
- deviceTypes: [DeviceType.AlarmPanel],
11320
- methods: {
11321
- arm: method(object({
11322
- deviceId: number().int().nonnegative(),
11323
- mode: AlarmArmModeSchema,
11324
- /** Optional PIN code. Required when `requiresCode === true`.
11325
- * Passed through to the upstream service; never persisted. */
11326
- code: string().min(1).optional()
11327
- }), _void(), {
11328
- kind: "mutation",
11329
- auth: "admin"
11330
- }),
11331
- disarm: method(object({
11332
- deviceId: number().int().nonnegative(),
11333
- code: string().min(1).optional()
11334
- }), _void(), {
11335
- kind: "mutation",
11336
- auth: "admin"
11337
- }),
11338
- /**
11339
- * Force the panel into the `triggered` state — used by HA
11340
- * automations to surface external sensor events through the panel
11341
- * (e.g. a Reolink camera intrusion event firing the security
11342
- * system). Provider rejects when the panel hardware doesn't
11343
- * support a software-initiated trigger.
11344
- */
11345
- trigger: method(object({ deviceId: number().int().nonnegative() }), _void(), {
11346
- kind: "mutation",
11347
- auth: "admin"
11348
- })
11349
- },
11350
- status: {
11351
- schema: AlarmPanelStatusSchema,
11352
- kind: "push"
11353
- },
11354
- /**
11355
- * Runtime-state slice — mirrored by the kernel. UI panel reads the
11356
- * full slice; renders an arm button per `availableModes` entry and
11357
- * a PIN field iff `requiresCode === true`.
11358
- */
11359
- runtimeState: AlarmPanelStatusSchema
11360
- };
11361
- /**
11362
11443
  * Ambient illuminance reading in lux. Drives Home Assistant `sensor`
11363
11444
  * entries with `device_class: illuminance`.
11364
11445
  */
@@ -18807,6 +18888,20 @@ var GetInputSchema = object({ id: string() });
18807
18888
  var AddInputSchema = object({
18808
18889
  kind: string().min(1),
18809
18890
  name: string().min(1),
18891
+ /**
18892
+ * ADOPT an existing id instead of minting a new one.
18893
+ *
18894
+ * Written the day this cost an outage. A broker's id is not a detail: HA
18895
+ * devices carry it inside their `stableId` (`ha:ha_004:dev:…`), so a broker
18896
+ * lost from config and re-added as `ha_001` leaves every one of its devices
18897
+ * bound to a broker that no longer exists. Re-entering the password under the
18898
+ * ORIGINAL id turns a multi-step device migration back into re-entering a
18899
+ * password.
18900
+ *
18901
+ * A provider MUST refuse an id that is already in use — adopting a live
18902
+ * broker's id would silently take it over.
18903
+ */
18904
+ id: string().min(1).optional(),
18810
18905
  /** Kind-specific settings (e.g. MQTT `{url,username,password}` or HA
18811
18906
  * `{baseUrl,accessToken}`). Validated by the kind-specific provider
18812
18907
  * branch on receipt — invalid shape rejects the add. */
@@ -28586,6 +28681,12 @@ Object.freeze({
28586
28681
  addonId: null,
28587
28682
  access: "delete"
28588
28683
  },
28684
+ "notificationRules.getAlarmConfig": {
28685
+ capName: "notification-rules",
28686
+ capScope: "system",
28687
+ addonId: null,
28688
+ access: "view"
28689
+ },
28589
28690
  "notificationRules.getConditionCatalog": {
28590
28691
  capName: "notification-rules",
28591
28692
  capScope: "system",
@@ -28616,6 +28717,12 @@ Object.freeze({
28616
28717
  addonId: null,
28617
28718
  access: "view"
28618
28719
  },
28720
+ "notificationRules.setAlarmConfig": {
28721
+ capName: "notification-rules",
28722
+ capScope: "system",
28723
+ addonId: null,
28724
+ access: "create"
28725
+ },
28619
28726
  "notificationRules.setRuleEnabled": {
28620
28727
  capName: "notification-rules",
28621
28728
  capScope: "system",