@alteriom/mqtt-schema 0.6.0 → 0.7.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 +105 -2
- package/dist/cjs/schema_data.d.ts +170 -1
- package/dist/cjs/schema_data.js +195 -1
- package/dist/cjs/schemas/firmware_status.schema.json +17 -2
- package/dist/cjs/schemas/ota/ota-manifest.schema.json +98 -0
- package/dist/cjs/schemas/validation_rules.md +10 -1
- package/dist/esm/schema_data.js +195 -1
- package/dist/esm/schemas/firmware_status.schema.json +17 -2
- package/dist/esm/schemas/ota/ota-manifest.schema.json +98 -0
- package/dist/esm/schemas/validation_rules.md +10 -1
- package/package.json +1 -1
- package/schemas/firmware_status.schema.json +17 -2
- package/schemas/ota/ota-manifest.schema.json +98 -0
- package/schemas/validation_rules.md +10 -1
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ Firmware emits structured MQTT payloads that must remain tightly aligned with we
|
|
|
33
33
|
- Helpful error paths (JSON Pointer style)
|
|
34
34
|
- Lightweight (Ajv peer dependency, schemas embedded)
|
|
35
35
|
- Ships original schema JSON files (optional consumption)
|
|
36
|
+
- **NEW in v0.7.0**: Best-in-class OTA management with security, rollback, and delta updates
|
|
36
37
|
- **NEW in v0.6.0**: Enhanced location/geolocation support for asset tracking
|
|
37
38
|
- **NEW in v0.6.0**: Extended sensor metadata (accuracy, calibration, operational range)
|
|
38
39
|
- **NEW in v0.6.0**: Comprehensive gateway health metrics (storage, network, errors)
|
|
@@ -292,9 +293,13 @@ if (result.valid && isGatewayMetricsMessage(metrics)) {
|
|
|
292
293
|
- Restart tracking with reason codes
|
|
293
294
|
- All metrics are optional for gradual firmware adoption
|
|
294
295
|
|
|
295
|
-
## OTA Firmware
|
|
296
|
+
## OTA Firmware Management (v0.7.0+)
|
|
296
297
|
|
|
297
|
-
|
|
298
|
+
Comprehensive best-in-class OTA solution based on 2024 industry standards.
|
|
299
|
+
|
|
300
|
+
### OTA Manifest Schema
|
|
301
|
+
|
|
302
|
+
The package includes OTA firmware manifest schema with both rich and minimal formats, enhanced with enterprise-grade features.
|
|
298
303
|
|
|
299
304
|
**Preferred: Stable alias import** (v0.3.1+):
|
|
300
305
|
```ts
|
|
@@ -329,6 +334,104 @@ Supported formats:
|
|
|
329
334
|
- **Minimal environment map**: environment → channels mapping
|
|
330
335
|
- **Chunk variants**: structured objects or SHA256 array
|
|
331
336
|
|
|
337
|
+
### Enhanced OTA Features (v0.7.0+)
|
|
338
|
+
|
|
339
|
+
**Security & Authenticity:**
|
|
340
|
+
```ts
|
|
341
|
+
const manifest = {
|
|
342
|
+
environment: "universal-sensor",
|
|
343
|
+
branch: "main",
|
|
344
|
+
manifests: {
|
|
345
|
+
prod: {
|
|
346
|
+
build_type: "prod",
|
|
347
|
+
file: "firmware-v2.0.0.bin",
|
|
348
|
+
size: 456789,
|
|
349
|
+
sha256: "a1b2c3...",
|
|
350
|
+
firmware_version: "2.0.0",
|
|
351
|
+
built: "2025-10-19T12:00:00Z",
|
|
352
|
+
ota_url: "https://firmware.example.com/v2.0.0.bin",
|
|
353
|
+
|
|
354
|
+
// Digital signature for authenticity
|
|
355
|
+
signature: "MEUCIQDx...",
|
|
356
|
+
signature_algorithm: "ECDSA-SHA256",
|
|
357
|
+
signing_key_id: "prod-signing-key-2025",
|
|
358
|
+
|
|
359
|
+
// Version constraints
|
|
360
|
+
min_version: "1.5.0", // Minimum version to upgrade from
|
|
361
|
+
max_version: "1.9.99", // Prevent downgrades
|
|
362
|
+
|
|
363
|
+
// Release management
|
|
364
|
+
release_notes_url: "https://docs.example.com/v2.0.0",
|
|
365
|
+
criticality: "high", // low | medium | high | critical
|
|
366
|
+
mandatory: true, // Must be installed
|
|
367
|
+
|
|
368
|
+
// Staged rollout
|
|
369
|
+
rollout_percentage: 25, // Start with 25% of fleet
|
|
370
|
+
rollout_target_groups: ["beta-testers", "early-adopters"],
|
|
371
|
+
|
|
372
|
+
// Delta updates (60-90% bandwidth reduction)
|
|
373
|
+
delta_from_version: "1.9.0",
|
|
374
|
+
delta_patch_url: "https://firmware.example.com/patches/1.9.0-to-2.0.0.patch",
|
|
375
|
+
delta_patch_size: 45678,
|
|
376
|
+
delta_patch_sha256: "c3d4e5..."
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Firmware Update Status Tracking:**
|
|
383
|
+
```ts
|
|
384
|
+
import { validators, isFirmwareStatusMessage } from '@alteriom/mqtt-schema';
|
|
385
|
+
|
|
386
|
+
// Enhanced status tracking
|
|
387
|
+
const status = {
|
|
388
|
+
schema_version: 1,
|
|
389
|
+
device_id: "SN789",
|
|
390
|
+
device_type: "sensor",
|
|
391
|
+
timestamp: new Date().toISOString(),
|
|
392
|
+
firmware_version: "2.0.0",
|
|
393
|
+
|
|
394
|
+
status: "downloading", // New: rolled_back, rollback_pending, rollback_failed
|
|
395
|
+
progress_pct: 42,
|
|
396
|
+
|
|
397
|
+
// Progress details
|
|
398
|
+
download_speed_kbps: 125.5,
|
|
399
|
+
bytes_downloaded: 196608,
|
|
400
|
+
bytes_total: 456789,
|
|
401
|
+
eta_seconds: 28,
|
|
402
|
+
|
|
403
|
+
// Rollback support
|
|
404
|
+
rollback_available: true,
|
|
405
|
+
previous_version: "1.9.0",
|
|
406
|
+
|
|
407
|
+
// Security verification
|
|
408
|
+
update_type: "delta", // full | delta | patch
|
|
409
|
+
signature_verified: true,
|
|
410
|
+
checksum_verified: true,
|
|
411
|
+
|
|
412
|
+
// Operational context
|
|
413
|
+
battery_level_pct: 85,
|
|
414
|
+
free_space_kb: 2048,
|
|
415
|
+
retry_count: 0
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const result = validators.firmwareStatus(status);
|
|
419
|
+
if (result.valid) {
|
|
420
|
+
console.log(`Download progress: ${status.progress_pct}% at ${status.download_speed_kbps} kbps`);
|
|
421
|
+
console.log(`ETA: ${status.eta_seconds} seconds`);
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**OTA Best Practices:**
|
|
426
|
+
- **Security**: Always use digital signatures for production firmware
|
|
427
|
+
- **Rollback**: Maintain backup partition for automatic rollback on failures
|
|
428
|
+
- **Delta Updates**: Use delta patches for bandwidth-constrained deployments (60-90% reduction)
|
|
429
|
+
- **Staged Rollout**: Start with 5-10% rollout, monitor, then expand gradually
|
|
430
|
+
- **Version Control**: Use min_version to prevent upgrades from incompatible versions
|
|
431
|
+
- **Criticality**: Mark security patches as "critical" with mandatory: true
|
|
432
|
+
|
|
433
|
+
See `docs/OTA_MANIFEST.md` for comprehensive guide and best practices.
|
|
434
|
+
|
|
332
435
|
## API Surface
|
|
333
436
|
|
|
334
437
|
```ts
|
|
@@ -408,7 +408,7 @@ export declare const firmware_status_schema: {
|
|
|
408
408
|
};
|
|
409
409
|
readonly status: {
|
|
410
410
|
readonly type: "string";
|
|
411
|
-
readonly enum: readonly ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed"];
|
|
411
|
+
readonly enum: readonly ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed", "rolled_back", "rollback_pending", "rollback_failed"];
|
|
412
412
|
};
|
|
413
413
|
readonly progress_pct: {
|
|
414
414
|
readonly type: "number";
|
|
@@ -418,6 +418,77 @@ export declare const firmware_status_schema: {
|
|
|
418
418
|
readonly error: {
|
|
419
419
|
readonly type: readonly ["string", "null"];
|
|
420
420
|
};
|
|
421
|
+
readonly error_code: {
|
|
422
|
+
readonly type: "string";
|
|
423
|
+
readonly description: "Machine-readable error code for diagnostics";
|
|
424
|
+
};
|
|
425
|
+
readonly retry_count: {
|
|
426
|
+
readonly type: "integer";
|
|
427
|
+
readonly minimum: 0;
|
|
428
|
+
readonly description: "Number of retry attempts for this update";
|
|
429
|
+
};
|
|
430
|
+
readonly download_speed_kbps: {
|
|
431
|
+
readonly type: "number";
|
|
432
|
+
readonly minimum: 0;
|
|
433
|
+
readonly description: "Current download speed in kilobits per second";
|
|
434
|
+
};
|
|
435
|
+
readonly bytes_downloaded: {
|
|
436
|
+
readonly type: "integer";
|
|
437
|
+
readonly minimum: 0;
|
|
438
|
+
readonly description: "Number of bytes downloaded so far";
|
|
439
|
+
};
|
|
440
|
+
readonly bytes_total: {
|
|
441
|
+
readonly type: "integer";
|
|
442
|
+
readonly minimum: 0;
|
|
443
|
+
readonly description: "Total bytes to download";
|
|
444
|
+
};
|
|
445
|
+
readonly eta_seconds: {
|
|
446
|
+
readonly type: "integer";
|
|
447
|
+
readonly minimum: 0;
|
|
448
|
+
readonly description: "Estimated time remaining in seconds";
|
|
449
|
+
};
|
|
450
|
+
readonly update_started_at: {
|
|
451
|
+
readonly type: "string";
|
|
452
|
+
readonly format: "date-time";
|
|
453
|
+
readonly description: "ISO8601 timestamp when update began";
|
|
454
|
+
};
|
|
455
|
+
readonly update_completed_at: {
|
|
456
|
+
readonly type: "string";
|
|
457
|
+
readonly format: "date-time";
|
|
458
|
+
readonly description: "ISO8601 timestamp when update completed or failed";
|
|
459
|
+
};
|
|
460
|
+
readonly rollback_available: {
|
|
461
|
+
readonly type: "boolean";
|
|
462
|
+
readonly description: "Whether rollback to previous version is available";
|
|
463
|
+
};
|
|
464
|
+
readonly previous_version: {
|
|
465
|
+
readonly type: "string";
|
|
466
|
+
readonly description: "Version to rollback to if update fails";
|
|
467
|
+
};
|
|
468
|
+
readonly update_type: {
|
|
469
|
+
readonly type: "string";
|
|
470
|
+
readonly enum: readonly ["full", "delta", "patch"];
|
|
471
|
+
readonly description: "Type of update being applied";
|
|
472
|
+
};
|
|
473
|
+
readonly signature_verified: {
|
|
474
|
+
readonly type: "boolean";
|
|
475
|
+
readonly description: "Whether firmware signature was successfully verified";
|
|
476
|
+
};
|
|
477
|
+
readonly checksum_verified: {
|
|
478
|
+
readonly type: "boolean";
|
|
479
|
+
readonly description: "Whether firmware checksum was successfully verified";
|
|
480
|
+
};
|
|
481
|
+
readonly free_space_kb: {
|
|
482
|
+
readonly type: "integer";
|
|
483
|
+
readonly minimum: 0;
|
|
484
|
+
readonly description: "Available storage space in kilobytes before update";
|
|
485
|
+
};
|
|
486
|
+
readonly battery_level_pct: {
|
|
487
|
+
readonly type: "number";
|
|
488
|
+
readonly minimum: 0;
|
|
489
|
+
readonly maximum: 100;
|
|
490
|
+
readonly description: "Battery level during update (critical for battery-powered devices)";
|
|
491
|
+
};
|
|
421
492
|
};
|
|
422
493
|
readonly additionalProperties: true;
|
|
423
494
|
};
|
|
@@ -862,6 +933,82 @@ export declare const ota_ota_manifest_schema: {
|
|
|
862
933
|
readonly description: "Array of SHA256 strings for chunks";
|
|
863
934
|
}];
|
|
864
935
|
};
|
|
936
|
+
readonly signature: {
|
|
937
|
+
readonly type: "string";
|
|
938
|
+
readonly description: "Digital signature of the firmware for authenticity verification (base64 encoded)";
|
|
939
|
+
};
|
|
940
|
+
readonly signature_algorithm: {
|
|
941
|
+
readonly type: "string";
|
|
942
|
+
readonly enum: readonly ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"];
|
|
943
|
+
readonly description: "Algorithm used for digital signature";
|
|
944
|
+
};
|
|
945
|
+
readonly signing_key_id: {
|
|
946
|
+
readonly type: "string";
|
|
947
|
+
readonly description: "Identifier of the signing key for key rotation support";
|
|
948
|
+
};
|
|
949
|
+
readonly release_notes_url: {
|
|
950
|
+
readonly type: "string";
|
|
951
|
+
readonly format: "uri";
|
|
952
|
+
readonly description: "URL to release notes or changelog for this version";
|
|
953
|
+
};
|
|
954
|
+
readonly min_version: {
|
|
955
|
+
readonly type: "string";
|
|
956
|
+
readonly description: "Minimum firmware version required to upgrade to this version";
|
|
957
|
+
};
|
|
958
|
+
readonly max_version: {
|
|
959
|
+
readonly type: "string";
|
|
960
|
+
readonly description: "Maximum firmware version that can upgrade to this version (for preventing downgrades)";
|
|
961
|
+
};
|
|
962
|
+
readonly criticality: {
|
|
963
|
+
readonly type: "string";
|
|
964
|
+
readonly enum: readonly ["low", "medium", "high", "critical"];
|
|
965
|
+
readonly description: "Update criticality level for prioritization";
|
|
966
|
+
};
|
|
967
|
+
readonly mandatory: {
|
|
968
|
+
readonly type: "boolean";
|
|
969
|
+
readonly description: "Whether this update must be installed (cannot be skipped)";
|
|
970
|
+
};
|
|
971
|
+
readonly rollout_percentage: {
|
|
972
|
+
readonly type: "number";
|
|
973
|
+
readonly minimum: 0;
|
|
974
|
+
readonly maximum: 100;
|
|
975
|
+
readonly description: "Percentage of fleet to receive this update (staged rollout)";
|
|
976
|
+
};
|
|
977
|
+
readonly rollout_target_groups: {
|
|
978
|
+
readonly type: "array";
|
|
979
|
+
readonly items: {
|
|
980
|
+
readonly type: "string";
|
|
981
|
+
};
|
|
982
|
+
readonly description: "Specific device groups targeted for this update (A/B testing)";
|
|
983
|
+
};
|
|
984
|
+
readonly delta_from_version: {
|
|
985
|
+
readonly type: "string";
|
|
986
|
+
readonly description: "Source version for delta/patch update";
|
|
987
|
+
};
|
|
988
|
+
readonly delta_patch_url: {
|
|
989
|
+
readonly type: "string";
|
|
990
|
+
readonly format: "uri";
|
|
991
|
+
readonly description: "URL to download delta patch instead of full firmware";
|
|
992
|
+
};
|
|
993
|
+
readonly delta_patch_size: {
|
|
994
|
+
readonly type: "integer";
|
|
995
|
+
readonly minimum: 1;
|
|
996
|
+
readonly description: "Size of delta patch in bytes";
|
|
997
|
+
};
|
|
998
|
+
readonly delta_patch_sha256: {
|
|
999
|
+
readonly type: "string";
|
|
1000
|
+
readonly pattern: "^[a-f0-9]{64}$";
|
|
1001
|
+
readonly description: "SHA256 hash of the delta patch file";
|
|
1002
|
+
};
|
|
1003
|
+
readonly deprecated: {
|
|
1004
|
+
readonly type: "boolean";
|
|
1005
|
+
readonly description: "Mark this version as deprecated (not recommended for new installs)";
|
|
1006
|
+
};
|
|
1007
|
+
readonly expiry_date: {
|
|
1008
|
+
readonly type: "string";
|
|
1009
|
+
readonly format: "date-time";
|
|
1010
|
+
readonly description: "ISO8601 timestamp when this firmware version expires and should no longer be installed";
|
|
1011
|
+
};
|
|
865
1012
|
};
|
|
866
1013
|
readonly required: readonly ["build_type", "file", "size", "sha256", "firmware_version", "built", "ota_url"];
|
|
867
1014
|
readonly additionalProperties: true;
|
|
@@ -923,6 +1070,28 @@ export declare const ota_ota_manifest_schema: {
|
|
|
923
1070
|
readonly format: "date-time";
|
|
924
1071
|
readonly description: "ISO8601 timestamp";
|
|
925
1072
|
};
|
|
1073
|
+
readonly signature: {
|
|
1074
|
+
readonly type: "string";
|
|
1075
|
+
readonly description: "Digital signature of the firmware (base64 encoded)";
|
|
1076
|
+
};
|
|
1077
|
+
readonly signature_algorithm: {
|
|
1078
|
+
readonly type: "string";
|
|
1079
|
+
readonly enum: readonly ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"];
|
|
1080
|
+
readonly description: "Algorithm used for digital signature";
|
|
1081
|
+
};
|
|
1082
|
+
readonly min_version: {
|
|
1083
|
+
readonly type: "string";
|
|
1084
|
+
readonly description: "Minimum firmware version required to upgrade";
|
|
1085
|
+
};
|
|
1086
|
+
readonly criticality: {
|
|
1087
|
+
readonly type: "string";
|
|
1088
|
+
readonly enum: readonly ["low", "medium", "high", "critical"];
|
|
1089
|
+
readonly description: "Update criticality level";
|
|
1090
|
+
};
|
|
1091
|
+
readonly mandatory: {
|
|
1092
|
+
readonly type: "boolean";
|
|
1093
|
+
readonly description: "Whether this update must be installed";
|
|
1094
|
+
};
|
|
926
1095
|
};
|
|
927
1096
|
readonly required: readonly ["file", "size", "sha256", "version", "timestamp"];
|
|
928
1097
|
readonly additionalProperties: true;
|
package/dist/cjs/schema_data.js
CHANGED
|
@@ -487,7 +487,10 @@ exports.firmware_status_schema = {
|
|
|
487
487
|
"verifying",
|
|
488
488
|
"rebooting",
|
|
489
489
|
"completed",
|
|
490
|
-
"failed"
|
|
490
|
+
"failed",
|
|
491
|
+
"rolled_back",
|
|
492
|
+
"rollback_pending",
|
|
493
|
+
"rollback_failed"
|
|
491
494
|
]
|
|
492
495
|
},
|
|
493
496
|
"progress_pct": {
|
|
@@ -500,6 +503,81 @@ exports.firmware_status_schema = {
|
|
|
500
503
|
"string",
|
|
501
504
|
"null"
|
|
502
505
|
]
|
|
506
|
+
},
|
|
507
|
+
"error_code": {
|
|
508
|
+
"type": "string",
|
|
509
|
+
"description": "Machine-readable error code for diagnostics"
|
|
510
|
+
},
|
|
511
|
+
"retry_count": {
|
|
512
|
+
"type": "integer",
|
|
513
|
+
"minimum": 0,
|
|
514
|
+
"description": "Number of retry attempts for this update"
|
|
515
|
+
},
|
|
516
|
+
"download_speed_kbps": {
|
|
517
|
+
"type": "number",
|
|
518
|
+
"minimum": 0,
|
|
519
|
+
"description": "Current download speed in kilobits per second"
|
|
520
|
+
},
|
|
521
|
+
"bytes_downloaded": {
|
|
522
|
+
"type": "integer",
|
|
523
|
+
"minimum": 0,
|
|
524
|
+
"description": "Number of bytes downloaded so far"
|
|
525
|
+
},
|
|
526
|
+
"bytes_total": {
|
|
527
|
+
"type": "integer",
|
|
528
|
+
"minimum": 0,
|
|
529
|
+
"description": "Total bytes to download"
|
|
530
|
+
},
|
|
531
|
+
"eta_seconds": {
|
|
532
|
+
"type": "integer",
|
|
533
|
+
"minimum": 0,
|
|
534
|
+
"description": "Estimated time remaining in seconds"
|
|
535
|
+
},
|
|
536
|
+
"update_started_at": {
|
|
537
|
+
"type": "string",
|
|
538
|
+
"format": "date-time",
|
|
539
|
+
"description": "ISO8601 timestamp when update began"
|
|
540
|
+
},
|
|
541
|
+
"update_completed_at": {
|
|
542
|
+
"type": "string",
|
|
543
|
+
"format": "date-time",
|
|
544
|
+
"description": "ISO8601 timestamp when update completed or failed"
|
|
545
|
+
},
|
|
546
|
+
"rollback_available": {
|
|
547
|
+
"type": "boolean",
|
|
548
|
+
"description": "Whether rollback to previous version is available"
|
|
549
|
+
},
|
|
550
|
+
"previous_version": {
|
|
551
|
+
"type": "string",
|
|
552
|
+
"description": "Version to rollback to if update fails"
|
|
553
|
+
},
|
|
554
|
+
"update_type": {
|
|
555
|
+
"type": "string",
|
|
556
|
+
"enum": [
|
|
557
|
+
"full",
|
|
558
|
+
"delta",
|
|
559
|
+
"patch"
|
|
560
|
+
],
|
|
561
|
+
"description": "Type of update being applied"
|
|
562
|
+
},
|
|
563
|
+
"signature_verified": {
|
|
564
|
+
"type": "boolean",
|
|
565
|
+
"description": "Whether firmware signature was successfully verified"
|
|
566
|
+
},
|
|
567
|
+
"checksum_verified": {
|
|
568
|
+
"type": "boolean",
|
|
569
|
+
"description": "Whether firmware checksum was successfully verified"
|
|
570
|
+
},
|
|
571
|
+
"free_space_kb": {
|
|
572
|
+
"type": "integer",
|
|
573
|
+
"minimum": 0,
|
|
574
|
+
"description": "Available storage space in kilobytes before update"
|
|
575
|
+
},
|
|
576
|
+
"battery_level_pct": {
|
|
577
|
+
"type": "number",
|
|
578
|
+
"minimum": 0,
|
|
579
|
+
"maximum": 100,
|
|
580
|
+
"description": "Battery level during update (critical for battery-powered devices)"
|
|
503
581
|
}
|
|
504
582
|
},
|
|
505
583
|
"additionalProperties": true
|
|
@@ -1046,6 +1124,91 @@ exports.ota_ota_manifest_schema = {
|
|
|
1046
1124
|
"description": "Array of SHA256 strings for chunks"
|
|
1047
1125
|
}
|
|
1048
1126
|
]
|
|
1127
|
+
},
|
|
1128
|
+
"signature": {
|
|
1129
|
+
"type": "string",
|
|
1130
|
+
"description": "Digital signature of the firmware for authenticity verification (base64 encoded)"
|
|
1131
|
+
},
|
|
1132
|
+
"signature_algorithm": {
|
|
1133
|
+
"type": "string",
|
|
1134
|
+
"enum": [
|
|
1135
|
+
"RSA-SHA256",
|
|
1136
|
+
"ECDSA-SHA256",
|
|
1137
|
+
"Ed25519"
|
|
1138
|
+
],
|
|
1139
|
+
"description": "Algorithm used for digital signature"
|
|
1140
|
+
},
|
|
1141
|
+
"signing_key_id": {
|
|
1142
|
+
"type": "string",
|
|
1143
|
+
"description": "Identifier of the signing key for key rotation support"
|
|
1144
|
+
},
|
|
1145
|
+
"release_notes_url": {
|
|
1146
|
+
"type": "string",
|
|
1147
|
+
"format": "uri",
|
|
1148
|
+
"description": "URL to release notes or changelog for this version"
|
|
1149
|
+
},
|
|
1150
|
+
"min_version": {
|
|
1151
|
+
"type": "string",
|
|
1152
|
+
"description": "Minimum firmware version required to upgrade to this version"
|
|
1153
|
+
},
|
|
1154
|
+
"max_version": {
|
|
1155
|
+
"type": "string",
|
|
1156
|
+
"description": "Maximum firmware version that can upgrade to this version (for preventing downgrades)"
|
|
1157
|
+
},
|
|
1158
|
+
"criticality": {
|
|
1159
|
+
"type": "string",
|
|
1160
|
+
"enum": [
|
|
1161
|
+
"low",
|
|
1162
|
+
"medium",
|
|
1163
|
+
"high",
|
|
1164
|
+
"critical"
|
|
1165
|
+
],
|
|
1166
|
+
"description": "Update criticality level for prioritization"
|
|
1167
|
+
},
|
|
1168
|
+
"mandatory": {
|
|
1169
|
+
"type": "boolean",
|
|
1170
|
+
"description": "Whether this update must be installed (cannot be skipped)"
|
|
1171
|
+
},
|
|
1172
|
+
"rollout_percentage": {
|
|
1173
|
+
"type": "number",
|
|
1174
|
+
"minimum": 0,
|
|
1175
|
+
"maximum": 100,
|
|
1176
|
+
"description": "Percentage of fleet to receive this update (staged rollout)"
|
|
1177
|
+
},
|
|
1178
|
+
"rollout_target_groups": {
|
|
1179
|
+
"type": "array",
|
|
1180
|
+
"items": {
|
|
1181
|
+
"type": "string"
|
|
1182
|
+
},
|
|
1183
|
+
"description": "Specific device groups targeted for this update (A/B testing)"
|
|
1184
|
+
},
|
|
1185
|
+
"delta_from_version": {
|
|
1186
|
+
"type": "string",
|
|
1187
|
+
"description": "Source version for delta/patch update"
|
|
1188
|
+
},
|
|
1189
|
+
"delta_patch_url": {
|
|
1190
|
+
"type": "string",
|
|
1191
|
+
"format": "uri",
|
|
1192
|
+
"description": "URL to download delta patch instead of full firmware"
|
|
1193
|
+
},
|
|
1194
|
+
"delta_patch_size": {
|
|
1195
|
+
"type": "integer",
|
|
1196
|
+
"minimum": 1,
|
|
1197
|
+
"description": "Size of delta patch in bytes"
|
|
1198
|
+
},
|
|
1199
|
+
"delta_patch_sha256": {
|
|
1200
|
+
"type": "string",
|
|
1201
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
1202
|
+
"description": "SHA256 hash of the delta patch file"
|
|
1203
|
+
},
|
|
1204
|
+
"deprecated": {
|
|
1205
|
+
"type": "boolean",
|
|
1206
|
+
"description": "Mark this version as deprecated (not recommended for new installs)"
|
|
1207
|
+
},
|
|
1208
|
+
"expiry_date": {
|
|
1209
|
+
"type": "string",
|
|
1210
|
+
"format": "date-time",
|
|
1211
|
+
"description": "ISO8601 timestamp when this firmware version expires and should no longer be installed"
|
|
1049
1212
|
}
|
|
1050
1213
|
},
|
|
1051
1214
|
"required": [
|
|
@@ -1120,6 +1283,37 @@ exports.ota_ota_manifest_schema = {
|
|
|
1120
1283
|
"type": "string",
|
|
1121
1284
|
"format": "date-time",
|
|
1122
1285
|
"description": "ISO8601 timestamp"
|
|
1286
|
+
},
|
|
1287
|
+
"signature": {
|
|
1288
|
+
"type": "string",
|
|
1289
|
+
"description": "Digital signature of the firmware (base64 encoded)"
|
|
1290
|
+
},
|
|
1291
|
+
"signature_algorithm": {
|
|
1292
|
+
"type": "string",
|
|
1293
|
+
"enum": [
|
|
1294
|
+
"RSA-SHA256",
|
|
1295
|
+
"ECDSA-SHA256",
|
|
1296
|
+
"Ed25519"
|
|
1297
|
+
],
|
|
1298
|
+
"description": "Algorithm used for digital signature"
|
|
1299
|
+
},
|
|
1300
|
+
"min_version": {
|
|
1301
|
+
"type": "string",
|
|
1302
|
+
"description": "Minimum firmware version required to upgrade"
|
|
1303
|
+
},
|
|
1304
|
+
"criticality": {
|
|
1305
|
+
"type": "string",
|
|
1306
|
+
"enum": [
|
|
1307
|
+
"low",
|
|
1308
|
+
"medium",
|
|
1309
|
+
"high",
|
|
1310
|
+
"critical"
|
|
1311
|
+
],
|
|
1312
|
+
"description": "Update criticality level"
|
|
1313
|
+
},
|
|
1314
|
+
"mandatory": {
|
|
1315
|
+
"type": "boolean",
|
|
1316
|
+
"description": "Whether this update must be installed"
|
|
1123
1317
|
}
|
|
1124
1318
|
},
|
|
1125
1319
|
"required": [
|
|
@@ -9,9 +9,24 @@
|
|
|
9
9
|
"event": {"type": "string"},
|
|
10
10
|
"from_version": {"type": "string"},
|
|
11
11
|
"to_version": {"type": "string"},
|
|
12
|
-
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed"]},
|
|
12
|
+
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed", "rolled_back", "rollback_pending", "rollback_failed"]},
|
|
13
13
|
"progress_pct": {"type": "number", "minimum": 0, "maximum": 100},
|
|
14
|
-
"error": {"type": ["string", "null"]}
|
|
14
|
+
"error": {"type": ["string", "null"]},
|
|
15
|
+
"error_code": {"type": "string", "description": "Machine-readable error code for diagnostics"},
|
|
16
|
+
"retry_count": {"type": "integer", "minimum": 0, "description": "Number of retry attempts for this update"},
|
|
17
|
+
"download_speed_kbps": {"type": "number", "minimum": 0, "description": "Current download speed in kilobits per second"},
|
|
18
|
+
"bytes_downloaded": {"type": "integer", "minimum": 0, "description": "Number of bytes downloaded so far"},
|
|
19
|
+
"bytes_total": {"type": "integer", "minimum": 0, "description": "Total bytes to download"},
|
|
20
|
+
"eta_seconds": {"type": "integer", "minimum": 0, "description": "Estimated time remaining in seconds"},
|
|
21
|
+
"update_started_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update began"},
|
|
22
|
+
"update_completed_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update completed or failed"},
|
|
23
|
+
"rollback_available": {"type": "boolean", "description": "Whether rollback to previous version is available"},
|
|
24
|
+
"previous_version": {"type": "string", "description": "Version to rollback to if update fails"},
|
|
25
|
+
"update_type": {"type": "string", "enum": ["full", "delta", "patch"], "description": "Type of update being applied"},
|
|
26
|
+
"signature_verified": {"type": "boolean", "description": "Whether firmware signature was successfully verified"},
|
|
27
|
+
"checksum_verified": {"type": "boolean", "description": "Whether firmware checksum was successfully verified"},
|
|
28
|
+
"free_space_kb": {"type": "integer", "minimum": 0, "description": "Available storage space in kilobytes before update"},
|
|
29
|
+
"battery_level_pct": {"type": "number", "minimum": 0, "maximum": 100, "description": "Battery level during update (critical for battery-powered devices)"}
|
|
15
30
|
},
|
|
16
31
|
"additionalProperties": true
|
|
17
32
|
}
|
|
@@ -117,6 +117,82 @@
|
|
|
117
117
|
"description": "Array of SHA256 strings for chunks"
|
|
118
118
|
}
|
|
119
119
|
]
|
|
120
|
+
},
|
|
121
|
+
"signature": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Digital signature of the firmware for authenticity verification (base64 encoded)"
|
|
124
|
+
},
|
|
125
|
+
"signature_algorithm": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
128
|
+
"description": "Algorithm used for digital signature"
|
|
129
|
+
},
|
|
130
|
+
"signing_key_id": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "Identifier of the signing key for key rotation support"
|
|
133
|
+
},
|
|
134
|
+
"release_notes_url": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"format": "uri",
|
|
137
|
+
"description": "URL to release notes or changelog for this version"
|
|
138
|
+
},
|
|
139
|
+
"min_version": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "Minimum firmware version required to upgrade to this version"
|
|
142
|
+
},
|
|
143
|
+
"max_version": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Maximum firmware version that can upgrade to this version (for preventing downgrades)"
|
|
146
|
+
},
|
|
147
|
+
"criticality": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
150
|
+
"description": "Update criticality level for prioritization"
|
|
151
|
+
},
|
|
152
|
+
"mandatory": {
|
|
153
|
+
"type": "boolean",
|
|
154
|
+
"description": "Whether this update must be installed (cannot be skipped)"
|
|
155
|
+
},
|
|
156
|
+
"rollout_percentage": {
|
|
157
|
+
"type": "number",
|
|
158
|
+
"minimum": 0,
|
|
159
|
+
"maximum": 100,
|
|
160
|
+
"description": "Percentage of fleet to receive this update (staged rollout)"
|
|
161
|
+
},
|
|
162
|
+
"rollout_target_groups": {
|
|
163
|
+
"type": "array",
|
|
164
|
+
"items": {
|
|
165
|
+
"type": "string"
|
|
166
|
+
},
|
|
167
|
+
"description": "Specific device groups targeted for this update (A/B testing)"
|
|
168
|
+
},
|
|
169
|
+
"delta_from_version": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"description": "Source version for delta/patch update"
|
|
172
|
+
},
|
|
173
|
+
"delta_patch_url": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"format": "uri",
|
|
176
|
+
"description": "URL to download delta patch instead of full firmware"
|
|
177
|
+
},
|
|
178
|
+
"delta_patch_size": {
|
|
179
|
+
"type": "integer",
|
|
180
|
+
"minimum": 1,
|
|
181
|
+
"description": "Size of delta patch in bytes"
|
|
182
|
+
},
|
|
183
|
+
"delta_patch_sha256": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
186
|
+
"description": "SHA256 hash of the delta patch file"
|
|
187
|
+
},
|
|
188
|
+
"deprecated": {
|
|
189
|
+
"type": "boolean",
|
|
190
|
+
"description": "Mark this version as deprecated (not recommended for new installs)"
|
|
191
|
+
},
|
|
192
|
+
"expiry_date": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"format": "date-time",
|
|
195
|
+
"description": "ISO8601 timestamp when this firmware version expires and should no longer be installed"
|
|
120
196
|
}
|
|
121
197
|
},
|
|
122
198
|
"required": ["build_type", "file", "size", "sha256", "firmware_version", "built", "ota_url"],
|
|
@@ -178,6 +254,28 @@
|
|
|
178
254
|
"type": "string",
|
|
179
255
|
"format": "date-time",
|
|
180
256
|
"description": "ISO8601 timestamp"
|
|
257
|
+
},
|
|
258
|
+
"signature": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "Digital signature of the firmware (base64 encoded)"
|
|
261
|
+
},
|
|
262
|
+
"signature_algorithm": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
265
|
+
"description": "Algorithm used for digital signature"
|
|
266
|
+
},
|
|
267
|
+
"min_version": {
|
|
268
|
+
"type": "string",
|
|
269
|
+
"description": "Minimum firmware version required to upgrade"
|
|
270
|
+
},
|
|
271
|
+
"criticality": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
274
|
+
"description": "Update criticality level"
|
|
275
|
+
},
|
|
276
|
+
"mandatory": {
|
|
277
|
+
"type": "boolean",
|
|
278
|
+
"description": "Whether this update must be installed"
|
|
181
279
|
}
|
|
182
280
|
},
|
|
183
281
|
"required": ["file", "size", "sha256", "version", "timestamp"],
|
|
@@ -48,8 +48,17 @@ This file captures dynamic / contextual validation that is OUTSIDE pure structur
|
|
|
48
48
|
- All count metrics must be >= 0.
|
|
49
49
|
|
|
50
50
|
## Firmware Update Status
|
|
51
|
-
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed.
|
|
51
|
+
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed, rolled_back, rollback_pending, rollback_failed.
|
|
52
52
|
- `progress_pct` (if present) must be 0–100.
|
|
53
|
+
- **NEW (OTA Enhancement)**:
|
|
54
|
+
- `retry_count` must be >= 0 (tracks update retry attempts).
|
|
55
|
+
- `download_speed_kbps`, `bytes_downloaded`, `bytes_total`, `eta_seconds` must be >= 0.
|
|
56
|
+
- `battery_level_pct` must be 0-100 (critical for battery-powered devices).
|
|
57
|
+
- `error_code` provides machine-readable error classification (e.g., VERIFY_CHECKSUM_MISMATCH).
|
|
58
|
+
- `update_type` must be one of: full, delta, patch.
|
|
59
|
+
- `signature_verified` and `checksum_verified` booleans indicate security verification status.
|
|
60
|
+
- `rollback_available` indicates whether automatic rollback is supported.
|
|
61
|
+
- `previous_version` stores the version to rollback to if update fails.
|
|
53
62
|
|
|
54
63
|
## Extensibility
|
|
55
64
|
- Unknown top-level keys tolerated (future evolution) except if they collide with any deprecated alias or reserved future keys announced in CHANGELOG.
|
package/dist/esm/schema_data.js
CHANGED
|
@@ -484,7 +484,10 @@ export const firmware_status_schema = {
|
|
|
484
484
|
"verifying",
|
|
485
485
|
"rebooting",
|
|
486
486
|
"completed",
|
|
487
|
-
"failed"
|
|
487
|
+
"failed",
|
|
488
|
+
"rolled_back",
|
|
489
|
+
"rollback_pending",
|
|
490
|
+
"rollback_failed"
|
|
488
491
|
]
|
|
489
492
|
},
|
|
490
493
|
"progress_pct": {
|
|
@@ -497,6 +500,81 @@ export const firmware_status_schema = {
|
|
|
497
500
|
"string",
|
|
498
501
|
"null"
|
|
499
502
|
]
|
|
503
|
+
},
|
|
504
|
+
"error_code": {
|
|
505
|
+
"type": "string",
|
|
506
|
+
"description": "Machine-readable error code for diagnostics"
|
|
507
|
+
},
|
|
508
|
+
"retry_count": {
|
|
509
|
+
"type": "integer",
|
|
510
|
+
"minimum": 0,
|
|
511
|
+
"description": "Number of retry attempts for this update"
|
|
512
|
+
},
|
|
513
|
+
"download_speed_kbps": {
|
|
514
|
+
"type": "number",
|
|
515
|
+
"minimum": 0,
|
|
516
|
+
"description": "Current download speed in kilobits per second"
|
|
517
|
+
},
|
|
518
|
+
"bytes_downloaded": {
|
|
519
|
+
"type": "integer",
|
|
520
|
+
"minimum": 0,
|
|
521
|
+
"description": "Number of bytes downloaded so far"
|
|
522
|
+
},
|
|
523
|
+
"bytes_total": {
|
|
524
|
+
"type": "integer",
|
|
525
|
+
"minimum": 0,
|
|
526
|
+
"description": "Total bytes to download"
|
|
527
|
+
},
|
|
528
|
+
"eta_seconds": {
|
|
529
|
+
"type": "integer",
|
|
530
|
+
"minimum": 0,
|
|
531
|
+
"description": "Estimated time remaining in seconds"
|
|
532
|
+
},
|
|
533
|
+
"update_started_at": {
|
|
534
|
+
"type": "string",
|
|
535
|
+
"format": "date-time",
|
|
536
|
+
"description": "ISO8601 timestamp when update began"
|
|
537
|
+
},
|
|
538
|
+
"update_completed_at": {
|
|
539
|
+
"type": "string",
|
|
540
|
+
"format": "date-time",
|
|
541
|
+
"description": "ISO8601 timestamp when update completed or failed"
|
|
542
|
+
},
|
|
543
|
+
"rollback_available": {
|
|
544
|
+
"type": "boolean",
|
|
545
|
+
"description": "Whether rollback to previous version is available"
|
|
546
|
+
},
|
|
547
|
+
"previous_version": {
|
|
548
|
+
"type": "string",
|
|
549
|
+
"description": "Version to rollback to if update fails"
|
|
550
|
+
},
|
|
551
|
+
"update_type": {
|
|
552
|
+
"type": "string",
|
|
553
|
+
"enum": [
|
|
554
|
+
"full",
|
|
555
|
+
"delta",
|
|
556
|
+
"patch"
|
|
557
|
+
],
|
|
558
|
+
"description": "Type of update being applied"
|
|
559
|
+
},
|
|
560
|
+
"signature_verified": {
|
|
561
|
+
"type": "boolean",
|
|
562
|
+
"description": "Whether firmware signature was successfully verified"
|
|
563
|
+
},
|
|
564
|
+
"checksum_verified": {
|
|
565
|
+
"type": "boolean",
|
|
566
|
+
"description": "Whether firmware checksum was successfully verified"
|
|
567
|
+
},
|
|
568
|
+
"free_space_kb": {
|
|
569
|
+
"type": "integer",
|
|
570
|
+
"minimum": 0,
|
|
571
|
+
"description": "Available storage space in kilobytes before update"
|
|
572
|
+
},
|
|
573
|
+
"battery_level_pct": {
|
|
574
|
+
"type": "number",
|
|
575
|
+
"minimum": 0,
|
|
576
|
+
"maximum": 100,
|
|
577
|
+
"description": "Battery level during update (critical for battery-powered devices)"
|
|
500
578
|
}
|
|
501
579
|
},
|
|
502
580
|
"additionalProperties": true
|
|
@@ -1043,6 +1121,91 @@ export const ota_ota_manifest_schema = {
|
|
|
1043
1121
|
"description": "Array of SHA256 strings for chunks"
|
|
1044
1122
|
}
|
|
1045
1123
|
]
|
|
1124
|
+
},
|
|
1125
|
+
"signature": {
|
|
1126
|
+
"type": "string",
|
|
1127
|
+
"description": "Digital signature of the firmware for authenticity verification (base64 encoded)"
|
|
1128
|
+
},
|
|
1129
|
+
"signature_algorithm": {
|
|
1130
|
+
"type": "string",
|
|
1131
|
+
"enum": [
|
|
1132
|
+
"RSA-SHA256",
|
|
1133
|
+
"ECDSA-SHA256",
|
|
1134
|
+
"Ed25519"
|
|
1135
|
+
],
|
|
1136
|
+
"description": "Algorithm used for digital signature"
|
|
1137
|
+
},
|
|
1138
|
+
"signing_key_id": {
|
|
1139
|
+
"type": "string",
|
|
1140
|
+
"description": "Identifier of the signing key for key rotation support"
|
|
1141
|
+
},
|
|
1142
|
+
"release_notes_url": {
|
|
1143
|
+
"type": "string",
|
|
1144
|
+
"format": "uri",
|
|
1145
|
+
"description": "URL to release notes or changelog for this version"
|
|
1146
|
+
},
|
|
1147
|
+
"min_version": {
|
|
1148
|
+
"type": "string",
|
|
1149
|
+
"description": "Minimum firmware version required to upgrade to this version"
|
|
1150
|
+
},
|
|
1151
|
+
"max_version": {
|
|
1152
|
+
"type": "string",
|
|
1153
|
+
"description": "Maximum firmware version that can upgrade to this version (for preventing downgrades)"
|
|
1154
|
+
},
|
|
1155
|
+
"criticality": {
|
|
1156
|
+
"type": "string",
|
|
1157
|
+
"enum": [
|
|
1158
|
+
"low",
|
|
1159
|
+
"medium",
|
|
1160
|
+
"high",
|
|
1161
|
+
"critical"
|
|
1162
|
+
],
|
|
1163
|
+
"description": "Update criticality level for prioritization"
|
|
1164
|
+
},
|
|
1165
|
+
"mandatory": {
|
|
1166
|
+
"type": "boolean",
|
|
1167
|
+
"description": "Whether this update must be installed (cannot be skipped)"
|
|
1168
|
+
},
|
|
1169
|
+
"rollout_percentage": {
|
|
1170
|
+
"type": "number",
|
|
1171
|
+
"minimum": 0,
|
|
1172
|
+
"maximum": 100,
|
|
1173
|
+
"description": "Percentage of fleet to receive this update (staged rollout)"
|
|
1174
|
+
},
|
|
1175
|
+
"rollout_target_groups": {
|
|
1176
|
+
"type": "array",
|
|
1177
|
+
"items": {
|
|
1178
|
+
"type": "string"
|
|
1179
|
+
},
|
|
1180
|
+
"description": "Specific device groups targeted for this update (A/B testing)"
|
|
1181
|
+
},
|
|
1182
|
+
"delta_from_version": {
|
|
1183
|
+
"type": "string",
|
|
1184
|
+
"description": "Source version for delta/patch update"
|
|
1185
|
+
},
|
|
1186
|
+
"delta_patch_url": {
|
|
1187
|
+
"type": "string",
|
|
1188
|
+
"format": "uri",
|
|
1189
|
+
"description": "URL to download delta patch instead of full firmware"
|
|
1190
|
+
},
|
|
1191
|
+
"delta_patch_size": {
|
|
1192
|
+
"type": "integer",
|
|
1193
|
+
"minimum": 1,
|
|
1194
|
+
"description": "Size of delta patch in bytes"
|
|
1195
|
+
},
|
|
1196
|
+
"delta_patch_sha256": {
|
|
1197
|
+
"type": "string",
|
|
1198
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
1199
|
+
"description": "SHA256 hash of the delta patch file"
|
|
1200
|
+
},
|
|
1201
|
+
"deprecated": {
|
|
1202
|
+
"type": "boolean",
|
|
1203
|
+
"description": "Mark this version as deprecated (not recommended for new installs)"
|
|
1204
|
+
},
|
|
1205
|
+
"expiry_date": {
|
|
1206
|
+
"type": "string",
|
|
1207
|
+
"format": "date-time",
|
|
1208
|
+
"description": "ISO8601 timestamp when this firmware version expires and should no longer be installed"
|
|
1046
1209
|
}
|
|
1047
1210
|
},
|
|
1048
1211
|
"required": [
|
|
@@ -1117,6 +1280,37 @@ export const ota_ota_manifest_schema = {
|
|
|
1117
1280
|
"type": "string",
|
|
1118
1281
|
"format": "date-time",
|
|
1119
1282
|
"description": "ISO8601 timestamp"
|
|
1283
|
+
},
|
|
1284
|
+
"signature": {
|
|
1285
|
+
"type": "string",
|
|
1286
|
+
"description": "Digital signature of the firmware (base64 encoded)"
|
|
1287
|
+
},
|
|
1288
|
+
"signature_algorithm": {
|
|
1289
|
+
"type": "string",
|
|
1290
|
+
"enum": [
|
|
1291
|
+
"RSA-SHA256",
|
|
1292
|
+
"ECDSA-SHA256",
|
|
1293
|
+
"Ed25519"
|
|
1294
|
+
],
|
|
1295
|
+
"description": "Algorithm used for digital signature"
|
|
1296
|
+
},
|
|
1297
|
+
"min_version": {
|
|
1298
|
+
"type": "string",
|
|
1299
|
+
"description": "Minimum firmware version required to upgrade"
|
|
1300
|
+
},
|
|
1301
|
+
"criticality": {
|
|
1302
|
+
"type": "string",
|
|
1303
|
+
"enum": [
|
|
1304
|
+
"low",
|
|
1305
|
+
"medium",
|
|
1306
|
+
"high",
|
|
1307
|
+
"critical"
|
|
1308
|
+
],
|
|
1309
|
+
"description": "Update criticality level"
|
|
1310
|
+
},
|
|
1311
|
+
"mandatory": {
|
|
1312
|
+
"type": "boolean",
|
|
1313
|
+
"description": "Whether this update must be installed"
|
|
1120
1314
|
}
|
|
1121
1315
|
},
|
|
1122
1316
|
"required": [
|
|
@@ -9,9 +9,24 @@
|
|
|
9
9
|
"event": {"type": "string"},
|
|
10
10
|
"from_version": {"type": "string"},
|
|
11
11
|
"to_version": {"type": "string"},
|
|
12
|
-
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed"]},
|
|
12
|
+
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed", "rolled_back", "rollback_pending", "rollback_failed"]},
|
|
13
13
|
"progress_pct": {"type": "number", "minimum": 0, "maximum": 100},
|
|
14
|
-
"error": {"type": ["string", "null"]}
|
|
14
|
+
"error": {"type": ["string", "null"]},
|
|
15
|
+
"error_code": {"type": "string", "description": "Machine-readable error code for diagnostics"},
|
|
16
|
+
"retry_count": {"type": "integer", "minimum": 0, "description": "Number of retry attempts for this update"},
|
|
17
|
+
"download_speed_kbps": {"type": "number", "minimum": 0, "description": "Current download speed in kilobits per second"},
|
|
18
|
+
"bytes_downloaded": {"type": "integer", "minimum": 0, "description": "Number of bytes downloaded so far"},
|
|
19
|
+
"bytes_total": {"type": "integer", "minimum": 0, "description": "Total bytes to download"},
|
|
20
|
+
"eta_seconds": {"type": "integer", "minimum": 0, "description": "Estimated time remaining in seconds"},
|
|
21
|
+
"update_started_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update began"},
|
|
22
|
+
"update_completed_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update completed or failed"},
|
|
23
|
+
"rollback_available": {"type": "boolean", "description": "Whether rollback to previous version is available"},
|
|
24
|
+
"previous_version": {"type": "string", "description": "Version to rollback to if update fails"},
|
|
25
|
+
"update_type": {"type": "string", "enum": ["full", "delta", "patch"], "description": "Type of update being applied"},
|
|
26
|
+
"signature_verified": {"type": "boolean", "description": "Whether firmware signature was successfully verified"},
|
|
27
|
+
"checksum_verified": {"type": "boolean", "description": "Whether firmware checksum was successfully verified"},
|
|
28
|
+
"free_space_kb": {"type": "integer", "minimum": 0, "description": "Available storage space in kilobytes before update"},
|
|
29
|
+
"battery_level_pct": {"type": "number", "minimum": 0, "maximum": 100, "description": "Battery level during update (critical for battery-powered devices)"}
|
|
15
30
|
},
|
|
16
31
|
"additionalProperties": true
|
|
17
32
|
}
|
|
@@ -117,6 +117,82 @@
|
|
|
117
117
|
"description": "Array of SHA256 strings for chunks"
|
|
118
118
|
}
|
|
119
119
|
]
|
|
120
|
+
},
|
|
121
|
+
"signature": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Digital signature of the firmware for authenticity verification (base64 encoded)"
|
|
124
|
+
},
|
|
125
|
+
"signature_algorithm": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
128
|
+
"description": "Algorithm used for digital signature"
|
|
129
|
+
},
|
|
130
|
+
"signing_key_id": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "Identifier of the signing key for key rotation support"
|
|
133
|
+
},
|
|
134
|
+
"release_notes_url": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"format": "uri",
|
|
137
|
+
"description": "URL to release notes or changelog for this version"
|
|
138
|
+
},
|
|
139
|
+
"min_version": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "Minimum firmware version required to upgrade to this version"
|
|
142
|
+
},
|
|
143
|
+
"max_version": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Maximum firmware version that can upgrade to this version (for preventing downgrades)"
|
|
146
|
+
},
|
|
147
|
+
"criticality": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
150
|
+
"description": "Update criticality level for prioritization"
|
|
151
|
+
},
|
|
152
|
+
"mandatory": {
|
|
153
|
+
"type": "boolean",
|
|
154
|
+
"description": "Whether this update must be installed (cannot be skipped)"
|
|
155
|
+
},
|
|
156
|
+
"rollout_percentage": {
|
|
157
|
+
"type": "number",
|
|
158
|
+
"minimum": 0,
|
|
159
|
+
"maximum": 100,
|
|
160
|
+
"description": "Percentage of fleet to receive this update (staged rollout)"
|
|
161
|
+
},
|
|
162
|
+
"rollout_target_groups": {
|
|
163
|
+
"type": "array",
|
|
164
|
+
"items": {
|
|
165
|
+
"type": "string"
|
|
166
|
+
},
|
|
167
|
+
"description": "Specific device groups targeted for this update (A/B testing)"
|
|
168
|
+
},
|
|
169
|
+
"delta_from_version": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"description": "Source version for delta/patch update"
|
|
172
|
+
},
|
|
173
|
+
"delta_patch_url": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"format": "uri",
|
|
176
|
+
"description": "URL to download delta patch instead of full firmware"
|
|
177
|
+
},
|
|
178
|
+
"delta_patch_size": {
|
|
179
|
+
"type": "integer",
|
|
180
|
+
"minimum": 1,
|
|
181
|
+
"description": "Size of delta patch in bytes"
|
|
182
|
+
},
|
|
183
|
+
"delta_patch_sha256": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
186
|
+
"description": "SHA256 hash of the delta patch file"
|
|
187
|
+
},
|
|
188
|
+
"deprecated": {
|
|
189
|
+
"type": "boolean",
|
|
190
|
+
"description": "Mark this version as deprecated (not recommended for new installs)"
|
|
191
|
+
},
|
|
192
|
+
"expiry_date": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"format": "date-time",
|
|
195
|
+
"description": "ISO8601 timestamp when this firmware version expires and should no longer be installed"
|
|
120
196
|
}
|
|
121
197
|
},
|
|
122
198
|
"required": ["build_type", "file", "size", "sha256", "firmware_version", "built", "ota_url"],
|
|
@@ -178,6 +254,28 @@
|
|
|
178
254
|
"type": "string",
|
|
179
255
|
"format": "date-time",
|
|
180
256
|
"description": "ISO8601 timestamp"
|
|
257
|
+
},
|
|
258
|
+
"signature": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "Digital signature of the firmware (base64 encoded)"
|
|
261
|
+
},
|
|
262
|
+
"signature_algorithm": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
265
|
+
"description": "Algorithm used for digital signature"
|
|
266
|
+
},
|
|
267
|
+
"min_version": {
|
|
268
|
+
"type": "string",
|
|
269
|
+
"description": "Minimum firmware version required to upgrade"
|
|
270
|
+
},
|
|
271
|
+
"criticality": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
274
|
+
"description": "Update criticality level"
|
|
275
|
+
},
|
|
276
|
+
"mandatory": {
|
|
277
|
+
"type": "boolean",
|
|
278
|
+
"description": "Whether this update must be installed"
|
|
181
279
|
}
|
|
182
280
|
},
|
|
183
281
|
"required": ["file", "size", "sha256", "version", "timestamp"],
|
|
@@ -48,8 +48,17 @@ This file captures dynamic / contextual validation that is OUTSIDE pure structur
|
|
|
48
48
|
- All count metrics must be >= 0.
|
|
49
49
|
|
|
50
50
|
## Firmware Update Status
|
|
51
|
-
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed.
|
|
51
|
+
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed, rolled_back, rollback_pending, rollback_failed.
|
|
52
52
|
- `progress_pct` (if present) must be 0–100.
|
|
53
|
+
- **NEW (OTA Enhancement)**:
|
|
54
|
+
- `retry_count` must be >= 0 (tracks update retry attempts).
|
|
55
|
+
- `download_speed_kbps`, `bytes_downloaded`, `bytes_total`, `eta_seconds` must be >= 0.
|
|
56
|
+
- `battery_level_pct` must be 0-100 (critical for battery-powered devices).
|
|
57
|
+
- `error_code` provides machine-readable error classification (e.g., VERIFY_CHECKSUM_MISMATCH).
|
|
58
|
+
- `update_type` must be one of: full, delta, patch.
|
|
59
|
+
- `signature_verified` and `checksum_verified` booleans indicate security verification status.
|
|
60
|
+
- `rollback_available` indicates whether automatic rollback is supported.
|
|
61
|
+
- `previous_version` stores the version to rollback to if update fails.
|
|
53
62
|
|
|
54
63
|
## Extensibility
|
|
55
64
|
- Unknown top-level keys tolerated (future evolution) except if they collide with any deprecated alias or reserved future keys announced in CHANGELOG.
|
package/package.json
CHANGED
|
@@ -9,9 +9,24 @@
|
|
|
9
9
|
"event": {"type": "string"},
|
|
10
10
|
"from_version": {"type": "string"},
|
|
11
11
|
"to_version": {"type": "string"},
|
|
12
|
-
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed"]},
|
|
12
|
+
"status": {"type": "string", "enum": ["pending", "downloading", "flashing", "verifying", "rebooting", "completed", "failed", "rolled_back", "rollback_pending", "rollback_failed"]},
|
|
13
13
|
"progress_pct": {"type": "number", "minimum": 0, "maximum": 100},
|
|
14
|
-
"error": {"type": ["string", "null"]}
|
|
14
|
+
"error": {"type": ["string", "null"]},
|
|
15
|
+
"error_code": {"type": "string", "description": "Machine-readable error code for diagnostics"},
|
|
16
|
+
"retry_count": {"type": "integer", "minimum": 0, "description": "Number of retry attempts for this update"},
|
|
17
|
+
"download_speed_kbps": {"type": "number", "minimum": 0, "description": "Current download speed in kilobits per second"},
|
|
18
|
+
"bytes_downloaded": {"type": "integer", "minimum": 0, "description": "Number of bytes downloaded so far"},
|
|
19
|
+
"bytes_total": {"type": "integer", "minimum": 0, "description": "Total bytes to download"},
|
|
20
|
+
"eta_seconds": {"type": "integer", "minimum": 0, "description": "Estimated time remaining in seconds"},
|
|
21
|
+
"update_started_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update began"},
|
|
22
|
+
"update_completed_at": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when update completed or failed"},
|
|
23
|
+
"rollback_available": {"type": "boolean", "description": "Whether rollback to previous version is available"},
|
|
24
|
+
"previous_version": {"type": "string", "description": "Version to rollback to if update fails"},
|
|
25
|
+
"update_type": {"type": "string", "enum": ["full", "delta", "patch"], "description": "Type of update being applied"},
|
|
26
|
+
"signature_verified": {"type": "boolean", "description": "Whether firmware signature was successfully verified"},
|
|
27
|
+
"checksum_verified": {"type": "boolean", "description": "Whether firmware checksum was successfully verified"},
|
|
28
|
+
"free_space_kb": {"type": "integer", "minimum": 0, "description": "Available storage space in kilobytes before update"},
|
|
29
|
+
"battery_level_pct": {"type": "number", "minimum": 0, "maximum": 100, "description": "Battery level during update (critical for battery-powered devices)"}
|
|
15
30
|
},
|
|
16
31
|
"additionalProperties": true
|
|
17
32
|
}
|
|
@@ -117,6 +117,82 @@
|
|
|
117
117
|
"description": "Array of SHA256 strings for chunks"
|
|
118
118
|
}
|
|
119
119
|
]
|
|
120
|
+
},
|
|
121
|
+
"signature": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Digital signature of the firmware for authenticity verification (base64 encoded)"
|
|
124
|
+
},
|
|
125
|
+
"signature_algorithm": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
128
|
+
"description": "Algorithm used for digital signature"
|
|
129
|
+
},
|
|
130
|
+
"signing_key_id": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "Identifier of the signing key for key rotation support"
|
|
133
|
+
},
|
|
134
|
+
"release_notes_url": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"format": "uri",
|
|
137
|
+
"description": "URL to release notes or changelog for this version"
|
|
138
|
+
},
|
|
139
|
+
"min_version": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "Minimum firmware version required to upgrade to this version"
|
|
142
|
+
},
|
|
143
|
+
"max_version": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Maximum firmware version that can upgrade to this version (for preventing downgrades)"
|
|
146
|
+
},
|
|
147
|
+
"criticality": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
150
|
+
"description": "Update criticality level for prioritization"
|
|
151
|
+
},
|
|
152
|
+
"mandatory": {
|
|
153
|
+
"type": "boolean",
|
|
154
|
+
"description": "Whether this update must be installed (cannot be skipped)"
|
|
155
|
+
},
|
|
156
|
+
"rollout_percentage": {
|
|
157
|
+
"type": "number",
|
|
158
|
+
"minimum": 0,
|
|
159
|
+
"maximum": 100,
|
|
160
|
+
"description": "Percentage of fleet to receive this update (staged rollout)"
|
|
161
|
+
},
|
|
162
|
+
"rollout_target_groups": {
|
|
163
|
+
"type": "array",
|
|
164
|
+
"items": {
|
|
165
|
+
"type": "string"
|
|
166
|
+
},
|
|
167
|
+
"description": "Specific device groups targeted for this update (A/B testing)"
|
|
168
|
+
},
|
|
169
|
+
"delta_from_version": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"description": "Source version for delta/patch update"
|
|
172
|
+
},
|
|
173
|
+
"delta_patch_url": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"format": "uri",
|
|
176
|
+
"description": "URL to download delta patch instead of full firmware"
|
|
177
|
+
},
|
|
178
|
+
"delta_patch_size": {
|
|
179
|
+
"type": "integer",
|
|
180
|
+
"minimum": 1,
|
|
181
|
+
"description": "Size of delta patch in bytes"
|
|
182
|
+
},
|
|
183
|
+
"delta_patch_sha256": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
186
|
+
"description": "SHA256 hash of the delta patch file"
|
|
187
|
+
},
|
|
188
|
+
"deprecated": {
|
|
189
|
+
"type": "boolean",
|
|
190
|
+
"description": "Mark this version as deprecated (not recommended for new installs)"
|
|
191
|
+
},
|
|
192
|
+
"expiry_date": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"format": "date-time",
|
|
195
|
+
"description": "ISO8601 timestamp when this firmware version expires and should no longer be installed"
|
|
120
196
|
}
|
|
121
197
|
},
|
|
122
198
|
"required": ["build_type", "file", "size", "sha256", "firmware_version", "built", "ota_url"],
|
|
@@ -178,6 +254,28 @@
|
|
|
178
254
|
"type": "string",
|
|
179
255
|
"format": "date-time",
|
|
180
256
|
"description": "ISO8601 timestamp"
|
|
257
|
+
},
|
|
258
|
+
"signature": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "Digital signature of the firmware (base64 encoded)"
|
|
261
|
+
},
|
|
262
|
+
"signature_algorithm": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"enum": ["RSA-SHA256", "ECDSA-SHA256", "Ed25519"],
|
|
265
|
+
"description": "Algorithm used for digital signature"
|
|
266
|
+
},
|
|
267
|
+
"min_version": {
|
|
268
|
+
"type": "string",
|
|
269
|
+
"description": "Minimum firmware version required to upgrade"
|
|
270
|
+
},
|
|
271
|
+
"criticality": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"enum": ["low", "medium", "high", "critical"],
|
|
274
|
+
"description": "Update criticality level"
|
|
275
|
+
},
|
|
276
|
+
"mandatory": {
|
|
277
|
+
"type": "boolean",
|
|
278
|
+
"description": "Whether this update must be installed"
|
|
181
279
|
}
|
|
182
280
|
},
|
|
183
281
|
"required": ["file", "size", "sha256", "version", "timestamp"],
|
|
@@ -48,8 +48,17 @@ This file captures dynamic / contextual validation that is OUTSIDE pure structur
|
|
|
48
48
|
- All count metrics must be >= 0.
|
|
49
49
|
|
|
50
50
|
## Firmware Update Status
|
|
51
|
-
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed.
|
|
51
|
+
- `status` must be one of: pending, downloading, flashing, verifying, rebooting, completed, failed, rolled_back, rollback_pending, rollback_failed.
|
|
52
52
|
- `progress_pct` (if present) must be 0–100.
|
|
53
|
+
- **NEW (OTA Enhancement)**:
|
|
54
|
+
- `retry_count` must be >= 0 (tracks update retry attempts).
|
|
55
|
+
- `download_speed_kbps`, `bytes_downloaded`, `bytes_total`, `eta_seconds` must be >= 0.
|
|
56
|
+
- `battery_level_pct` must be 0-100 (critical for battery-powered devices).
|
|
57
|
+
- `error_code` provides machine-readable error classification (e.g., VERIFY_CHECKSUM_MISMATCH).
|
|
58
|
+
- `update_type` must be one of: full, delta, patch.
|
|
59
|
+
- `signature_verified` and `checksum_verified` booleans indicate security verification status.
|
|
60
|
+
- `rollback_available` indicates whether automatic rollback is supported.
|
|
61
|
+
- `previous_version` stores the version to rollback to if update fails.
|
|
53
62
|
|
|
54
63
|
## Extensibility
|
|
55
64
|
- Unknown top-level keys tolerated (future evolution) except if they collide with any deprecated alias or reserved future keys announced in CHANGELOG.
|