@alteriom/mqtt-schema 0.3.1 → 0.4.0

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/README.md CHANGED
@@ -173,6 +173,9 @@ All Ajv validator functions are compiled once at module load. For typical web us
173
173
  | gateway_metrics.schema.json | Gateway performance metrics |
174
174
  | firmware_status.schema.json | Firmware update lifecycle events |
175
175
  | control_response.schema.json | Command/control response messages |
176
+ | mesh_node_list.schema.json | Mesh network node list with status |
177
+ | mesh_topology.schema.json | Mesh network topology and connections |
178
+ | mesh_alert.schema.json | Mesh network alerts and warnings |
176
179
 
177
180
  ## Exports
178
181
 
@@ -187,12 +190,15 @@ All Ajv validator functions are compiled once at module load. For typical web us
187
190
 
188
191
  ### Validator Keys
189
192
 
190
- `sensorData`, `sensorHeartbeat`, `sensorStatus`, `gatewayInfo`, `gatewayMetrics`, `firmwareStatus`, `controlResponse`
193
+ `sensorData`, `sensorHeartbeat`, `sensorStatus`, `gatewayInfo`, `gatewayMetrics`, `firmwareStatus`, `controlResponse`, `meshNodeList`, `meshTopology`, `meshAlert`
191
194
 
192
195
  ### Classification Heuristics (Simplified)
193
196
 
194
197
  - `metrics` → `gatewayMetrics`
195
198
  - `sensors` → `sensorData`
199
+ - `nodes` array → `meshNodeList`
200
+ - `connections` array → `meshTopology`
201
+ - `alerts` array → `meshAlert`
196
202
  - `progress_pct` or OTA status keywords → `firmwareStatus`
197
203
  - `status` + `device_type: sensor` → `sensorStatus`
198
204
  - `status: ok|error` (no other match) → `controlResponse`
@@ -226,7 +232,38 @@ Backward‑compatible additions: new optional properties or enums, documented in
226
232
 
227
233
  Issues & PRs welcome. Ensure firmware repo schemas remain the authoritative source—do not manually edit generated `schema_data.ts`.
228
234
 
229
- **Before opening a PR:** Run `npm run verify` to validate schemas, changelog, and tests.
235
+ ### Development Workflow
236
+
237
+ **Before opening a PR:** Run the comprehensive validation suite:
238
+
239
+ ```bash
240
+ npm run verify # Schema sync + changelog + fixtures
241
+ npm run verify:all # Additional schema compilation + OTA manifest validation
242
+ npm test # Enhanced fixture validation with detailed reporting
243
+ ```
244
+
245
+ **Available validation scripts:**
246
+ - `npm run test` - Cross-platform fixture validation (CJS/ESM) with enhanced error reporting
247
+ - `npm run test:ota` - OTA manifest fixture validation
248
+ - `npm run verify:schemas` - Ensure schemas are synced from source directory
249
+ - `npm run verify:release` - Check changelog contains current version
250
+ - `npm run verify:all` - Comprehensive schema compilation and fixture validation
251
+
252
+ ### Script Organization
253
+
254
+ Scripts are organized by category in `package.json`:
255
+ - **Build Scripts**: `build`, `build:cjs`, `build:esm`, `clean`, etc.
256
+ - **Testing & Validation**: `test`, `verify:*`, etc.
257
+ - **Release Management**: `release:prepare`, `wiki:generate`
258
+ - **Repository Metadata**: `metadata:*` (organization compliance)
259
+
260
+ ### Release Process
261
+
262
+ See `PUBLISH_CHECKLIST.md` for detailed release procedures. Quick summary:
263
+ 1. Update schemas in `docs/mqtt_schema/`
264
+ 2. Run `npm run verify` to ensure everything is valid
265
+ 3. Use `npm run release:prepare -- patch|minor|major` for version bumping
266
+ 4. Follow checklist for tagging and publishing
230
267
 
231
268
  ## Security
232
269
 
@@ -84,7 +84,49 @@ export interface ControlResponseMessage extends BaseEnvelope {
84
84
  message?: string;
85
85
  result?: unknown;
86
86
  }
87
- export type AnyMqttV1Message = SensorDataMessage | SensorHeartbeatMessage | SensorStatusMessage | GatewayInfoMessage | GatewayMetricsMessage | FirmwareStatusMessage | ControlResponseMessage;
87
+ export interface MeshNodeListMessage extends BaseEnvelope {
88
+ device_type: 'gateway';
89
+ firmware_version: string;
90
+ nodes: Array<{
91
+ node_id: string;
92
+ status?: 'online' | 'offline' | 'unreachable';
93
+ last_seen?: string;
94
+ signal_strength?: number;
95
+ [k: string]: unknown;
96
+ }>;
97
+ node_count?: number;
98
+ mesh_id?: string;
99
+ }
100
+ export interface MeshTopologyMessage extends BaseEnvelope {
101
+ device_type: 'gateway';
102
+ firmware_version: string;
103
+ connections: Array<{
104
+ from_node: string;
105
+ to_node: string;
106
+ link_quality?: number;
107
+ latency_ms?: number;
108
+ hop_count?: number;
109
+ [k: string]: unknown;
110
+ }>;
111
+ root_node?: string;
112
+ total_connections?: number;
113
+ }
114
+ export interface MeshAlertMessage extends BaseEnvelope {
115
+ device_type: 'gateway';
116
+ firmware_version: string;
117
+ alerts: Array<{
118
+ alert_type: 'low_memory' | 'node_offline' | 'connection_lost' | 'high_latency' | 'packet_loss' | 'firmware_mismatch' | 'configuration_error' | 'security_warning' | 'other';
119
+ severity: 'critical' | 'warning' | 'info';
120
+ message: string;
121
+ node_id?: string;
122
+ metric_value?: number;
123
+ threshold?: number;
124
+ alert_id?: string;
125
+ [k: string]: unknown;
126
+ }>;
127
+ alert_count?: number;
128
+ }
129
+ export type AnyMqttV1Message = SensorDataMessage | SensorHeartbeatMessage | SensorStatusMessage | GatewayInfoMessage | GatewayMetricsMessage | FirmwareStatusMessage | ControlResponseMessage | MeshNodeListMessage | MeshTopologyMessage | MeshAlertMessage;
88
130
  export declare function isSensorDataMessage(msg: any): msg is SensorDataMessage;
89
131
  export declare function isSensorHeartbeatMessage(msg: any): msg is SensorHeartbeatMessage;
90
132
  export declare function isSensorStatusMessage(msg: any): msg is SensorStatusMessage;
@@ -92,6 +134,9 @@ export declare function isGatewayInfoMessage(msg: any): msg is GatewayInfoMessag
92
134
  export declare function isGatewayMetricsMessage(msg: any): msg is GatewayMetricsMessage;
93
135
  export declare function isFirmwareStatusMessage(msg: any): msg is FirmwareStatusMessage;
94
136
  export declare function isControlResponseMessage(msg: any): msg is ControlResponseMessage;
137
+ export declare function isMeshNodeListMessage(msg: any): msg is MeshNodeListMessage;
138
+ export declare function isMeshTopologyMessage(msg: any): msg is MeshTopologyMessage;
139
+ export declare function isMeshAlertMessage(msg: any): msg is MeshAlertMessage;
95
140
  export declare function classifyMessage(msg: any): AnyMqttV1Message | null;
96
141
  export interface BasicValidationIssue {
97
142
  field?: string;
@@ -13,6 +13,9 @@ exports.isGatewayInfoMessage = isGatewayInfoMessage;
13
13
  exports.isGatewayMetricsMessage = isGatewayMetricsMessage;
14
14
  exports.isFirmwareStatusMessage = isFirmwareStatusMessage;
15
15
  exports.isControlResponseMessage = isControlResponseMessage;
16
+ exports.isMeshNodeListMessage = isMeshNodeListMessage;
17
+ exports.isMeshTopologyMessage = isMeshTopologyMessage;
18
+ exports.isMeshAlertMessage = isMeshAlertMessage;
16
19
  exports.classifyMessage = classifyMessage;
17
20
  exports.basicValidate = basicValidate;
18
21
  exports.parseMessage = parseMessage;
@@ -38,11 +41,26 @@ function isFirmwareStatusMessage(msg) {
38
41
  function isControlResponseMessage(msg) {
39
42
  return msg && msg.schema_version === 1 && (msg.status === 'ok' || msg.status === 'error') && 'timestamp' in msg;
40
43
  }
44
+ function isMeshNodeListMessage(msg) {
45
+ return msg && msg.schema_version === 1 && msg.device_type === 'gateway' && Array.isArray(msg.nodes);
46
+ }
47
+ function isMeshTopologyMessage(msg) {
48
+ return msg && msg.schema_version === 1 && msg.device_type === 'gateway' && Array.isArray(msg.connections);
49
+ }
50
+ function isMeshAlertMessage(msg) {
51
+ return msg && msg.schema_version === 1 && msg.device_type === 'gateway' && Array.isArray(msg.alerts);
52
+ }
41
53
  function classifyMessage(msg) {
42
54
  if (isSensorDataMessage(msg))
43
55
  return msg;
44
56
  if (isGatewayMetricsMessage(msg))
45
57
  return msg;
58
+ if (isMeshNodeListMessage(msg))
59
+ return msg;
60
+ if (isMeshTopologyMessage(msg))
61
+ return msg;
62
+ if (isMeshAlertMessage(msg))
63
+ return msg;
46
64
  if (isSensorStatusMessage(msg))
47
65
  return msg;
48
66
  if (isGatewayInfoMessage(msg))
@@ -303,6 +303,172 @@ export declare const control_response_schema: {
303
303
  };
304
304
  readonly additionalProperties: true;
305
305
  };
306
+ export declare const mesh_node_list_schema: {
307
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
308
+ readonly $id: "https://schemas.alteriom.io/mqtt/v1/mesh_node_list.schema.json";
309
+ readonly title: "Mesh Node List v1";
310
+ readonly allOf: readonly [{
311
+ readonly $ref: "envelope.schema.json";
312
+ }];
313
+ readonly type: "object";
314
+ readonly required: readonly ["nodes"];
315
+ readonly properties: {
316
+ readonly nodes: {
317
+ readonly type: "array";
318
+ readonly items: {
319
+ readonly type: "object";
320
+ readonly required: readonly ["node_id"];
321
+ readonly properties: {
322
+ readonly node_id: {
323
+ readonly type: "string";
324
+ readonly description: "Unique node identifier";
325
+ };
326
+ readonly status: {
327
+ readonly type: "string";
328
+ readonly enum: readonly ["online", "offline", "unreachable"];
329
+ readonly description: "Current node status";
330
+ };
331
+ readonly last_seen: {
332
+ readonly type: "string";
333
+ readonly format: "date-time";
334
+ readonly description: "Last communication timestamp";
335
+ };
336
+ readonly signal_strength: {
337
+ readonly type: "integer";
338
+ readonly minimum: -200;
339
+ readonly maximum: 0;
340
+ readonly description: "Signal strength in dBm";
341
+ };
342
+ };
343
+ readonly additionalProperties: true;
344
+ };
345
+ };
346
+ readonly node_count: {
347
+ readonly type: "integer";
348
+ readonly minimum: 0;
349
+ readonly description: "Total number of nodes";
350
+ };
351
+ readonly mesh_id: {
352
+ readonly type: "string";
353
+ readonly description: "Mesh network identifier";
354
+ };
355
+ };
356
+ readonly additionalProperties: true;
357
+ };
358
+ export declare const mesh_topology_schema: {
359
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
360
+ readonly $id: "https://schemas.alteriom.io/mqtt/v1/mesh_topology.schema.json";
361
+ readonly title: "Mesh Network Topology v1";
362
+ readonly allOf: readonly [{
363
+ readonly $ref: "envelope.schema.json";
364
+ }];
365
+ readonly type: "object";
366
+ readonly required: readonly ["connections"];
367
+ readonly properties: {
368
+ readonly connections: {
369
+ readonly type: "array";
370
+ readonly items: {
371
+ readonly type: "object";
372
+ readonly required: readonly ["from_node", "to_node"];
373
+ readonly properties: {
374
+ readonly from_node: {
375
+ readonly type: "string";
376
+ readonly description: "Source node ID";
377
+ };
378
+ readonly to_node: {
379
+ readonly type: "string";
380
+ readonly description: "Destination node ID";
381
+ };
382
+ readonly link_quality: {
383
+ readonly type: "number";
384
+ readonly minimum: 0;
385
+ readonly maximum: 1;
386
+ readonly description: "Link quality score (0-1)";
387
+ };
388
+ readonly latency_ms: {
389
+ readonly type: "integer";
390
+ readonly minimum: 0;
391
+ readonly description: "Link latency in milliseconds";
392
+ };
393
+ readonly hop_count: {
394
+ readonly type: "integer";
395
+ readonly minimum: 1;
396
+ readonly description: "Number of hops in path";
397
+ };
398
+ };
399
+ readonly additionalProperties: true;
400
+ };
401
+ };
402
+ readonly root_node: {
403
+ readonly type: "string";
404
+ readonly description: "Root node ID (gateway/bridge)";
405
+ };
406
+ readonly total_connections: {
407
+ readonly type: "integer";
408
+ readonly minimum: 0;
409
+ readonly description: "Total number of connections";
410
+ };
411
+ };
412
+ readonly additionalProperties: true;
413
+ };
414
+ export declare const mesh_alert_schema: {
415
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
416
+ readonly $id: "https://schemas.alteriom.io/mqtt/v1/mesh_alert.schema.json";
417
+ readonly title: "Mesh Network Alert v1";
418
+ readonly allOf: readonly [{
419
+ readonly $ref: "envelope.schema.json";
420
+ }];
421
+ readonly type: "object";
422
+ readonly required: readonly ["alerts"];
423
+ readonly properties: {
424
+ readonly alerts: {
425
+ readonly type: "array";
426
+ readonly items: {
427
+ readonly type: "object";
428
+ readonly required: readonly ["alert_type", "severity", "message"];
429
+ readonly properties: {
430
+ readonly alert_type: {
431
+ readonly type: "string";
432
+ readonly enum: readonly ["low_memory", "node_offline", "connection_lost", "high_latency", "packet_loss", "firmware_mismatch", "configuration_error", "security_warning", "other"];
433
+ readonly description: "Type of alert";
434
+ };
435
+ readonly severity: {
436
+ readonly type: "string";
437
+ readonly enum: readonly ["critical", "warning", "info"];
438
+ readonly description: "Alert severity level";
439
+ };
440
+ readonly message: {
441
+ readonly type: "string";
442
+ readonly description: "Human-readable alert message";
443
+ };
444
+ readonly node_id: {
445
+ readonly type: "string";
446
+ readonly description: "Related node ID (if applicable)";
447
+ };
448
+ readonly metric_value: {
449
+ readonly type: "number";
450
+ readonly description: "Related metric value (if applicable)";
451
+ };
452
+ readonly threshold: {
453
+ readonly type: "number";
454
+ readonly description: "Threshold that triggered alert";
455
+ };
456
+ readonly alert_id: {
457
+ readonly type: "string";
458
+ readonly description: "Unique alert identifier";
459
+ };
460
+ };
461
+ readonly additionalProperties: true;
462
+ };
463
+ };
464
+ readonly alert_count: {
465
+ readonly type: "integer";
466
+ readonly minimum: 0;
467
+ readonly description: "Total number of active alerts";
468
+ };
469
+ };
470
+ readonly additionalProperties: true;
471
+ };
306
472
  export declare const mqtt_v1_bundle_json: {
307
473
  readonly $comment: "Convenience bundle referencing all v1 schema artifact filenames for tooling discovery.";
308
474
  readonly version: 1;
@@ -315,6 +481,9 @@ export declare const mqtt_v1_bundle_json: {
315
481
  readonly gateway_metrics: "gateway_metrics.schema.json";
316
482
  readonly firmware_status: "firmware_status.schema.json";
317
483
  readonly control_response: "control_response.schema.json";
484
+ readonly mesh_node_list: "mesh_node_list.schema.json";
485
+ readonly mesh_topology: "mesh_topology.schema.json";
486
+ readonly mesh_alert: "mesh_alert.schema.json";
318
487
  };
319
488
  };
320
489
  export declare const ota_ota_manifest_schema: {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ota_ota_manifest_schema = exports.mqtt_v1_bundle_json = exports.control_response_schema = exports.firmware_status_schema = exports.gateway_metrics_schema = exports.gateway_info_schema = exports.sensor_status_schema = exports.sensor_heartbeat_schema = exports.sensor_data_schema = exports.envelope_schema = void 0;
3
+ exports.ota_ota_manifest_schema = exports.mqtt_v1_bundle_json = exports.mesh_alert_schema = exports.mesh_topology_schema = exports.mesh_node_list_schema = exports.control_response_schema = exports.firmware_status_schema = exports.gateway_metrics_schema = exports.gateway_info_schema = exports.sensor_status_schema = exports.sensor_heartbeat_schema = exports.sensor_data_schema = exports.envelope_schema = void 0;
4
4
  // AUTO-GENERATED by copy-schemas.cjs. Do not edit manually.
5
5
  /* eslint-disable */
6
6
  exports.envelope_schema = {
@@ -386,6 +386,211 @@ exports.control_response_schema = {
386
386
  },
387
387
  "additionalProperties": true
388
388
  };
389
+ exports.mesh_node_list_schema = {
390
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
391
+ "$id": "https://schemas.alteriom.io/mqtt/v1/mesh_node_list.schema.json",
392
+ "title": "Mesh Node List v1",
393
+ "allOf": [
394
+ {
395
+ "$ref": "envelope.schema.json"
396
+ }
397
+ ],
398
+ "type": "object",
399
+ "required": [
400
+ "nodes"
401
+ ],
402
+ "properties": {
403
+ "nodes": {
404
+ "type": "array",
405
+ "items": {
406
+ "type": "object",
407
+ "required": [
408
+ "node_id"
409
+ ],
410
+ "properties": {
411
+ "node_id": {
412
+ "type": "string",
413
+ "description": "Unique node identifier"
414
+ },
415
+ "status": {
416
+ "type": "string",
417
+ "enum": [
418
+ "online",
419
+ "offline",
420
+ "unreachable"
421
+ ],
422
+ "description": "Current node status"
423
+ },
424
+ "last_seen": {
425
+ "type": "string",
426
+ "format": "date-time",
427
+ "description": "Last communication timestamp"
428
+ },
429
+ "signal_strength": {
430
+ "type": "integer",
431
+ "minimum": -200,
432
+ "maximum": 0,
433
+ "description": "Signal strength in dBm"
434
+ }
435
+ },
436
+ "additionalProperties": true
437
+ }
438
+ },
439
+ "node_count": {
440
+ "type": "integer",
441
+ "minimum": 0,
442
+ "description": "Total number of nodes"
443
+ },
444
+ "mesh_id": {
445
+ "type": "string",
446
+ "description": "Mesh network identifier"
447
+ }
448
+ },
449
+ "additionalProperties": true
450
+ };
451
+ exports.mesh_topology_schema = {
452
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
453
+ "$id": "https://schemas.alteriom.io/mqtt/v1/mesh_topology.schema.json",
454
+ "title": "Mesh Network Topology v1",
455
+ "allOf": [
456
+ {
457
+ "$ref": "envelope.schema.json"
458
+ }
459
+ ],
460
+ "type": "object",
461
+ "required": [
462
+ "connections"
463
+ ],
464
+ "properties": {
465
+ "connections": {
466
+ "type": "array",
467
+ "items": {
468
+ "type": "object",
469
+ "required": [
470
+ "from_node",
471
+ "to_node"
472
+ ],
473
+ "properties": {
474
+ "from_node": {
475
+ "type": "string",
476
+ "description": "Source node ID"
477
+ },
478
+ "to_node": {
479
+ "type": "string",
480
+ "description": "Destination node ID"
481
+ },
482
+ "link_quality": {
483
+ "type": "number",
484
+ "minimum": 0,
485
+ "maximum": 1,
486
+ "description": "Link quality score (0-1)"
487
+ },
488
+ "latency_ms": {
489
+ "type": "integer",
490
+ "minimum": 0,
491
+ "description": "Link latency in milliseconds"
492
+ },
493
+ "hop_count": {
494
+ "type": "integer",
495
+ "minimum": 1,
496
+ "description": "Number of hops in path"
497
+ }
498
+ },
499
+ "additionalProperties": true
500
+ }
501
+ },
502
+ "root_node": {
503
+ "type": "string",
504
+ "description": "Root node ID (gateway/bridge)"
505
+ },
506
+ "total_connections": {
507
+ "type": "integer",
508
+ "minimum": 0,
509
+ "description": "Total number of connections"
510
+ }
511
+ },
512
+ "additionalProperties": true
513
+ };
514
+ exports.mesh_alert_schema = {
515
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
516
+ "$id": "https://schemas.alteriom.io/mqtt/v1/mesh_alert.schema.json",
517
+ "title": "Mesh Network Alert v1",
518
+ "allOf": [
519
+ {
520
+ "$ref": "envelope.schema.json"
521
+ }
522
+ ],
523
+ "type": "object",
524
+ "required": [
525
+ "alerts"
526
+ ],
527
+ "properties": {
528
+ "alerts": {
529
+ "type": "array",
530
+ "items": {
531
+ "type": "object",
532
+ "required": [
533
+ "alert_type",
534
+ "severity",
535
+ "message"
536
+ ],
537
+ "properties": {
538
+ "alert_type": {
539
+ "type": "string",
540
+ "enum": [
541
+ "low_memory",
542
+ "node_offline",
543
+ "connection_lost",
544
+ "high_latency",
545
+ "packet_loss",
546
+ "firmware_mismatch",
547
+ "configuration_error",
548
+ "security_warning",
549
+ "other"
550
+ ],
551
+ "description": "Type of alert"
552
+ },
553
+ "severity": {
554
+ "type": "string",
555
+ "enum": [
556
+ "critical",
557
+ "warning",
558
+ "info"
559
+ ],
560
+ "description": "Alert severity level"
561
+ },
562
+ "message": {
563
+ "type": "string",
564
+ "description": "Human-readable alert message"
565
+ },
566
+ "node_id": {
567
+ "type": "string",
568
+ "description": "Related node ID (if applicable)"
569
+ },
570
+ "metric_value": {
571
+ "type": "number",
572
+ "description": "Related metric value (if applicable)"
573
+ },
574
+ "threshold": {
575
+ "type": "number",
576
+ "description": "Threshold that triggered alert"
577
+ },
578
+ "alert_id": {
579
+ "type": "string",
580
+ "description": "Unique alert identifier"
581
+ }
582
+ },
583
+ "additionalProperties": true
584
+ }
585
+ },
586
+ "alert_count": {
587
+ "type": "integer",
588
+ "minimum": 0,
589
+ "description": "Total number of active alerts"
590
+ }
591
+ },
592
+ "additionalProperties": true
593
+ };
389
594
  exports.mqtt_v1_bundle_json = {
390
595
  "$comment": "Convenience bundle referencing all v1 schema artifact filenames for tooling discovery.",
391
596
  "version": 1,
@@ -397,7 +602,10 @@ exports.mqtt_v1_bundle_json = {
397
602
  "gateway_info": "gateway_info.schema.json",
398
603
  "gateway_metrics": "gateway_metrics.schema.json",
399
604
  "firmware_status": "firmware_status.schema.json",
400
- "control_response": "control_response.schema.json"
605
+ "control_response": "control_response.schema.json",
606
+ "mesh_node_list": "mesh_node_list.schema.json",
607
+ "mesh_topology": "mesh_topology.schema.json",
608
+ "mesh_alert": "mesh_alert.schema.json"
401
609
  }
402
610
  };
403
611
  exports.ota_ota_manifest_schema = {
@@ -0,0 +1,66 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.alteriom.io/mqtt/v1/mesh_alert.schema.json",
4
+ "title": "Mesh Network Alert v1",
5
+ "allOf": [{"$ref": "envelope.schema.json"}],
6
+ "type": "object",
7
+ "required": ["alerts"],
8
+ "properties": {
9
+ "alerts": {
10
+ "type": "array",
11
+ "items": {
12
+ "type": "object",
13
+ "required": ["alert_type", "severity", "message"],
14
+ "properties": {
15
+ "alert_type": {
16
+ "type": "string",
17
+ "enum": [
18
+ "low_memory",
19
+ "node_offline",
20
+ "connection_lost",
21
+ "high_latency",
22
+ "packet_loss",
23
+ "firmware_mismatch",
24
+ "configuration_error",
25
+ "security_warning",
26
+ "other"
27
+ ],
28
+ "description": "Type of alert"
29
+ },
30
+ "severity": {
31
+ "type": "string",
32
+ "enum": ["critical", "warning", "info"],
33
+ "description": "Alert severity level"
34
+ },
35
+ "message": {
36
+ "type": "string",
37
+ "description": "Human-readable alert message"
38
+ },
39
+ "node_id": {
40
+ "type": "string",
41
+ "description": "Related node ID (if applicable)"
42
+ },
43
+ "metric_value": {
44
+ "type": "number",
45
+ "description": "Related metric value (if applicable)"
46
+ },
47
+ "threshold": {
48
+ "type": "number",
49
+ "description": "Threshold that triggered alert"
50
+ },
51
+ "alert_id": {
52
+ "type": "string",
53
+ "description": "Unique alert identifier"
54
+ }
55
+ },
56
+ "additionalProperties": true
57
+ }
58
+ },
59
+ "alert_count": {
60
+ "type": "integer",
61
+ "minimum": 0,
62
+ "description": "Total number of active alerts"
63
+ }
64
+ },
65
+ "additionalProperties": true
66
+ }