@onekeyfe/hd-core 1.2.0-alpha.96 → 1.2.0-alpha.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +84 -404
  2. package/__tests__/firmware-update/device-update-bootloader.test.ts +2 -6
  3. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -9
  4. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +112 -0
  5. package/__tests__/firmware-update/firmware-update-plan.test.ts +70 -131
  6. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +1 -53
  7. package/__tests__/protocol-v2-resources.test.ts +232 -148
  8. package/__tests__/protocol-v2.test.ts +517 -1106
  9. package/dist/api/CheckAllFirmwareRelease.d.ts +3 -2
  10. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  11. package/dist/api/CheckBLEFirmwareRelease.d.ts +2 -3
  12. package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
  13. package/dist/api/CheckBootloaderRelease.d.ts +1 -2
  14. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  15. package/dist/api/CheckFirmwareRelease.d.ts +2 -3
  16. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  17. package/dist/api/FirmwareUpdateV2.d.ts +0 -1
  18. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  19. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  20. package/dist/api/FirmwareUpdateV4.d.ts +8 -6
  21. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  22. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  23. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  24. package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
  25. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
  26. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  27. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +1 -48
  28. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  29. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  30. package/dist/api/firmware/getBinary.d.ts +1 -0
  31. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  32. package/dist/data-manager/DataManager.d.ts +3 -4
  33. package/dist/data-manager/DataManager.d.ts.map +1 -1
  34. package/dist/index.d.ts +111 -103
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +849 -1313
  37. package/dist/protocols/protocol-v2/resources.d.ts +28 -10
  38. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  39. package/dist/types/api/checkAllFirmwareRelease.d.ts +8 -20
  40. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  41. package/dist/types/api/checkBLEFirmwareRelease.d.ts +13 -2
  42. package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
  43. package/dist/types/api/checkBootloaderRelease.d.ts +6 -2
  44. package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
  45. package/dist/types/api/checkFirmwareRelease.d.ts +13 -2
  46. package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
  47. package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
  48. package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
  49. package/dist/types/api/export.d.ts +1 -1
  50. package/dist/types/api/export.d.ts.map +1 -1
  51. package/dist/types/api/firmwareUpdate.d.ts +11 -3
  52. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  53. package/dist/types/settings.d.ts +36 -35
  54. package/dist/types/settings.d.ts.map +1 -1
  55. package/package.json +4 -4
  56. package/src/api/CheckAllFirmwareRelease.ts +80 -108
  57. package/src/api/CheckBLEFirmwareRelease.ts +5 -37
  58. package/src/api/CheckBootloaderRelease.ts +3 -35
  59. package/src/api/CheckFirmwareRelease.ts +7 -35
  60. package/src/api/FirmwareUpdateV2.ts +3 -15
  61. package/src/api/FirmwareUpdateV3.ts +7 -29
  62. package/src/api/FirmwareUpdateV4.ts +407 -824
  63. package/src/api/UploadPortfolio.ts +0 -18
  64. package/src/api/device/DeviceUpdateBootloader.ts +5 -26
  65. package/src/api/firmware/FirmwareHostBinding.ts +3 -16
  66. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +2 -0
  67. package/src/api/firmware/FirmwareUpdatePlan.ts +88 -226
  68. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +3 -10
  69. package/src/data-manager/DataManager.ts +19 -35
  70. package/src/index.ts +0 -10
  71. package/src/protocols/protocol-v2/resources.ts +341 -157
  72. package/src/types/api/checkAllFirmwareRelease.ts +12 -27
  73. package/src/types/api/checkBLEFirmwareRelease.ts +13 -4
  74. package/src/types/api/checkBootloaderRelease.ts +6 -2
  75. package/src/types/api/checkFirmwareRelease.ts +13 -2
  76. package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
  77. package/src/types/api/export.ts +1 -6
  78. package/src/types/api/firmwareUpdate.ts +16 -10
  79. package/src/types/settings.ts +61 -35
  80. package/src/utils/deviceFeaturesUtils.ts +2 -2
  81. package/__tests__/check-firmware-release-protocol-v2.test.ts +0 -199
  82. package/__tests__/firmware-memory-host.test.ts +0 -112
  83. package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +0 -469
  84. package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
  85. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
  86. package/dist/api/firmware/protocolV2Release.d.ts +0 -33
  87. package/dist/api/firmware/protocolV2Release.d.ts.map +0 -1
  88. package/src/api/firmware/FirmwareMemoryHost.ts +0 -142
  89. package/src/api/firmware/protocolV2Release.ts +0 -168
@@ -5,6 +5,7 @@ import CheckAllFirmwareRelease, {
5
5
  } from '../src/api/CheckAllFirmwareRelease';
6
6
  import { DataManager } from '../src/data-manager';
7
7
  import { createCoreApi } from '../src/inject';
8
+ import { PROTOCOL_V2_RESOURCE_DEVICE_PATHS } from '../src/protocols/protocol-v2/resources';
8
9
 
9
10
  import type { CoreApi } from '../src/types/api';
10
11
  import type { DeviceStateVersions, IFirmwareReleaseInfo } from '../src/types';
@@ -25,11 +26,6 @@ const currentVersions: DeviceStateVersions = {
25
26
  se04: '1.0.0',
26
27
  };
27
28
 
28
- const validComponentIntegrity = {
29
- expectedSize: 1024,
30
- fingerprint: '1'.repeat(64),
31
- };
32
-
33
29
  const release: IFirmwareReleaseInfo = {
34
30
  required: true,
35
31
  version: [2, 0, 0],
@@ -45,25 +41,21 @@ const release: IFirmwareReleaseInfo = {
45
41
  target: 'BOOTLOADER',
46
42
  url: 'https://example.com/bootloader.bin',
47
43
  version: [1, 1, 0],
48
- ...validComponentIntegrity,
49
44
  },
50
45
  applicationP1: {
51
46
  target: 'APPLICATION_P1',
52
47
  url: 'https://example.com/application-p1.bin',
53
48
  version: [2, 0, 0],
54
- ...validComponentIntegrity,
55
49
  },
56
50
  se02: {
57
51
  target: 'SE02',
58
52
  url: 'https://example.com/se02.bin',
59
53
  version: [2, 0, 0],
60
- ...validComponentIntegrity,
61
54
  },
62
55
  se03: {
63
56
  target: 'SE03',
64
57
  url: 'https://example.com/se03.bin',
65
58
  version: [1, 0, 0],
66
- ...validComponentIntegrity,
67
59
  },
68
60
  romloader: {
69
61
  target: 'ROMLOADER',
@@ -71,12 +63,77 @@ const release: IFirmwareReleaseInfo = {
71
63
  version: [2, 0, 0],
72
64
  },
73
65
  },
66
+ resourceBundles: [
67
+ {
68
+ name: 'images',
69
+ url: 'https://example.com/images.okpkg',
70
+ devicePath: 'vol0:/bundles/images/images.okpkg',
71
+ version: [1, 0, 0],
72
+ },
73
+ ],
74
74
  };
75
75
 
76
- const resourceSource = {
77
- archiveUrl: 'https://example.com/pro2-resource/pro2-resource.zip',
78
- archiveSha256: 'a'.repeat(64),
79
- archiveSize: 16_815_479,
76
+ const stableResources = ['images', 'animation', 'wallpaper', 'translations', 'roobert', 'noto'].map(
77
+ (type, index) => ({
78
+ type,
79
+ url: `https://example.com/${type}.okpkg`,
80
+ size: 0x52a0 + index + 1,
81
+ fileHash: 'a'.repeat(64),
82
+ headerHash: index.toString(16).padStart(128, '0'),
83
+ })
84
+ );
85
+
86
+ const createFilesystemTypedCall = (missingAll = false) => {
87
+ const resourceByPath = new Map(
88
+ stableResources.map(resource => [
89
+ PROTOCOL_V2_RESOURCE_DEVICE_PATHS[
90
+ resource.type as keyof typeof PROTOCOL_V2_RESOURCE_DEVICE_PATHS
91
+ ],
92
+ resource,
93
+ ])
94
+ );
95
+ return jest.fn((requestType: string, _responseType: string, payload: Record<string, any>) => {
96
+ if (requestType === 'ResourceInventoryGet') {
97
+ throw new Error('ResourceInventoryGet is unavailable on released firmware');
98
+ }
99
+ if (requestType === 'FilesystemPathInfoQuery') {
100
+ const resource = resourceByPath.get(payload.path);
101
+ return {
102
+ message: {
103
+ exist: Boolean(resource) && !missingAll,
104
+ directory: false,
105
+ size: missingAll ? 0 : resource?.size,
106
+ },
107
+ };
108
+ }
109
+ if (requestType === 'FilesystemFileRead') {
110
+ const resource = resourceByPath.get(payload.file.path);
111
+ if (!resource || missingAll) throw new Error('missing resource');
112
+ const header = new Uint8Array(0x52a0);
113
+ const view = new DataView(header.buffer);
114
+ 'OKPP'.split('').forEach((char, index) => {
115
+ header[index] = char.charCodeAt(0);
116
+ });
117
+ 'RESC'.split('').forEach((char, index) => {
118
+ header[0x08 + index] = char.charCodeAt(0);
119
+ });
120
+ view.setUint32(0x0c, header.byteLength, true);
121
+ for (let index = 0; index < resource.headerHash.length / 2; index++) {
122
+ header[0x240 + index] = Number.parseInt(
123
+ resource.headerHash.slice(index * 2, index * 2 + 2),
124
+ 16
125
+ );
126
+ }
127
+ const offset = Number(payload.file.offset);
128
+ const chunkLength = Number(payload.chunk_len);
129
+ return {
130
+ message: {
131
+ data: header.slice(offset, offset + chunkLength),
132
+ },
133
+ };
134
+ }
135
+ throw new Error(`Unexpected request: ${requestType}`);
136
+ });
80
137
  };
81
138
 
82
139
  describe('checkAllFirmwareRelease Protocol V2 support', () => {
@@ -153,6 +210,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
153
210
  test('detects same-version package hotfixes by P1 and P2 payload hash', () => {
154
211
  const packageSet: IFirmwareReleaseInfo = {
155
212
  ...release,
213
+ resourceBundles: undefined,
156
214
  installOrder: ['applicationP1', 'applicationP2'],
157
215
  components: {
158
216
  applicationP1: {
@@ -203,6 +261,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
203
261
  const packageSet: IFirmwareReleaseInfo = {
204
262
  ...release,
205
263
  required: false,
264
+ resourceBundles: undefined,
206
265
  installOrder: ['applicationP1'],
207
266
  components: {
208
267
  applicationP1: {
@@ -233,6 +292,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
233
292
  const packageSet: IFirmwareReleaseInfo = {
234
293
  ...release,
235
294
  required: false,
295
+ resourceBundles: undefined,
236
296
  installOrder: ['applicationP1'],
237
297
  components: {
238
298
  applicationP1: {
@@ -263,6 +323,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
263
323
  test('updates both application packages when normal mode only reports P1', () => {
264
324
  const packageSet: IFirmwareReleaseInfo = {
265
325
  ...release,
326
+ resourceBundles: undefined,
266
327
  installOrder: ['applicationP1', 'applicationP2'],
267
328
  components: {
268
329
  applicationP1: {
@@ -309,7 +370,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
309
370
  status: { mode: 'normal' },
310
371
  versions: currentVersions,
311
372
  });
312
- const typedCall = jest.fn();
373
+ const typedCall = createFilesystemTypedCall(true);
313
374
  method.device = {
314
375
  isProtocolV2: () => true,
315
376
  features: {
@@ -320,24 +381,14 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
320
381
  getCommands: () => ({ typedCall }),
321
382
  } as unknown as CheckAllFirmwareRelease['device'];
322
383
  jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
323
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
384
+ jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
324
385
 
325
386
  await expect(method.run()).resolves.toMatchObject({
326
387
  protocol: 'V2',
327
388
  deviceType: 'pro2',
328
389
  status: 'required',
329
390
  resourceStatus: 'unknown',
330
- resourceArchive: resourceSource,
331
391
  targetsToUpdate: ['boot', 'app_v1'],
332
- firmwareUpdatePlan: {
333
- executor: 'v4',
334
- platform: 'web',
335
- artifacts: [
336
- { artifactId: 'component:boot', target: 'boot' },
337
- { artifactId: 'component:app_v1', target: 'app_v1' },
338
- ],
339
- targetsToUpdate: ['boot', 'app_v1'],
340
- },
341
392
  firmware: {
342
393
  status: 'required',
343
394
  },
@@ -349,337 +400,11 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
349
400
  expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
350
401
  });
351
402
 
352
- test('preserves platform and forced firmware targets in the Protocol V2 prepared plan', async () => {
353
- const method = new CheckAllFirmwareRelease({
354
- id: 1,
355
- payload: {
356
- method: 'checkAllFirmwareRelease',
357
- firmwareType: EFirmwareType.Universal,
358
- platform: 'native',
359
- forceUpdateTargets: ['firmware'],
360
- },
361
- });
362
- method.init();
363
- method.device = {
364
- isProtocolV2: () => true,
365
- features: {
366
- deviceType: 'pro2',
367
- serialNo: 'pro2-device-id',
368
- firmwareVersion: '1.0.0',
369
- },
370
- getDeviceState: jest.fn().mockResolvedValue({
371
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
372
- status: { mode: 'normal' },
373
- versions: currentVersions,
374
- }),
375
- } as unknown as CheckAllFirmwareRelease['device'];
376
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
377
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
378
-
379
- await expect(method.run()).resolves.toMatchObject({
380
- targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
381
- firmwareUpdatePlan: {
382
- executor: 'v4',
383
- deviceIdentity: 'pro2-device-id',
384
- platform: 'native',
385
- artifacts: [
386
- { artifactId: 'component:boot', target: 'boot' },
387
- { artifactId: 'component:app_v1', target: 'app_v1' },
388
- { artifactId: 'component:se02', target: 'se02' },
389
- { artifactId: 'component:se03', target: 'se03' },
390
- ],
391
- targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
392
- },
393
- });
394
- });
395
-
396
- test('includes exact Protocol V2 developer force targets in the prepared plan', async () => {
397
- const currentRelease: IFirmwareReleaseInfo = {
398
- ...release,
399
- required: false,
400
- version: [1, 0, 0],
401
- installOrder: ['applicationP1', 'coprocessor'],
402
- components: {
403
- applicationP1: {
404
- target: 'APPLICATION_P1',
405
- url: 'https://example.com/application-p1.okpkg',
406
- version: [1, 0, 0],
407
- ...validComponentIntegrity,
408
- },
409
- coprocessor: {
410
- target: 'COPROCESSOR',
411
- url: 'https://example.com/coprocessor.okpkg',
412
- version: [1, 0, 0],
413
- ...validComponentIntegrity,
414
- },
415
- },
416
- };
417
- const method = new CheckAllFirmwareRelease({
418
- id: 1,
419
- payload: {
420
- method: 'checkAllFirmwareRelease',
421
- platform: 'desktop',
422
- protocolV2ForceUpdateTargets: ['app_v1', 'coprocessor'],
423
- },
424
- });
425
- method.init();
426
- method.device = {
427
- isProtocolV2: () => true,
428
- features: {
429
- deviceType: 'pro2',
430
- serialNo: 'pro2-device-id',
431
- firmwareVersion: '1.0.0',
432
- },
433
- getDeviceState: jest.fn().mockResolvedValue({
434
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
435
- status: { mode: 'normal' },
436
- versions: { ...currentVersions, applicationP1: '1.0.0' },
437
- }),
438
- } as unknown as CheckAllFirmwareRelease['device'];
439
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
440
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
441
-
442
- await expect(method.run()).resolves.toMatchObject({
443
- targetsToUpdate: ['app_v1', 'coprocessor'],
444
- firmwareUpdatePlan: {
445
- executor: 'v4',
446
- platform: 'desktop',
447
- artifacts: [
448
- { artifactId: 'component:app_v1', target: 'app_v1' },
449
- { artifactId: 'component:coprocessor', target: 'coprocessor' },
450
- ],
451
- targetsToUpdate: ['app_v1', 'coprocessor'],
452
- },
453
- });
454
- });
455
-
456
- test('builds a Desktop V4 prepared update without device identity', async () => {
457
- const currentRelease: IFirmwareReleaseInfo = {
458
- ...release,
459
- required: false,
460
- version: [1, 0, 0],
461
- installOrder: ['applicationP1'],
462
- components: {
463
- applicationP1: {
464
- target: 'APPLICATION_P1',
465
- url: 'https://example.com/application-p1.okpkg',
466
- version: [1, 0, 0],
467
- ...validComponentIntegrity,
468
- },
469
- },
470
- };
471
- const method = new CheckAllFirmwareRelease({
472
- id: 1,
473
- payload: {
474
- method: 'checkAllFirmwareRelease',
475
- platform: 'desktop',
476
- protocolV2ForceUpdateTargets: ['app_v1'],
477
- },
478
- });
479
- method.init();
480
- method.device = {
481
- isProtocolV2: () => true,
482
- features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
483
- getDeviceState: jest.fn().mockResolvedValue({
484
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
485
- status: { mode: 'normal' },
486
- versions: { ...currentVersions, applicationP1: '1.0.0' },
487
- }),
488
- } as unknown as CheckAllFirmwareRelease['device'];
489
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
490
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
491
-
492
- await expect(method.run()).resolves.toMatchObject({
493
- firmwareUpdatePlan: {
494
- executor: 'v4',
495
- deviceIdentity: 'unavailable',
496
- },
497
- });
498
- });
499
-
500
- test('rejects Neo-only unsupported exact secure-element targets', async () => {
501
- const neoRelease: IFirmwareReleaseInfo = {
502
- ...release,
503
- required: false,
504
- installOrder: ['se03'],
505
- components: {
506
- se03: {
507
- target: 'SE03',
508
- url: 'https://example.com/se03.okpkg',
509
- version: [1, 0, 0],
510
- },
511
- },
512
- };
513
- const method = new CheckAllFirmwareRelease({
514
- id: 1,
515
- payload: {
516
- method: 'checkAllFirmwareRelease',
517
- protocolV2ForceUpdateTargets: ['se03'],
518
- },
519
- });
520
- method.init();
521
- method.device = {
522
- isProtocolV2: () => true,
523
- features: { deviceType: 'neo', firmwareVersion: '1.0.0' },
524
- getDeviceState: jest.fn().mockResolvedValue({
525
- identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
526
- status: { mode: 'normal' },
527
- versions: currentVersions,
528
- }),
529
- } as unknown as CheckAllFirmwareRelease['device'];
530
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
531
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
532
-
533
- await expect(method.run()).rejects.toMatchObject({
534
- params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
535
- });
536
- });
537
-
538
- test('builds a V4 plan for Neo and excludes unsupported secure elements when forced', async () => {
539
- const neoRelease: IFirmwareReleaseInfo = {
540
- ...release,
541
- installOrder: ['se01', 'se02', 'se03', 'se04'],
542
- components: {
543
- se01: {
544
- target: 'SE01',
545
- url: 'https://example.com/se01.bin',
546
- version: [1, 0, 0],
547
- ...validComponentIntegrity,
548
- },
549
- se02: {
550
- target: 'SE02',
551
- url: 'https://example.com/se02.bin',
552
- version: [2, 0, 0],
553
- ...validComponentIntegrity,
554
- },
555
- se03: { target: 'SE03', url: 'https://example.com/se03.bin', version: [1, 0, 0] },
556
- se04: { target: 'SE04', url: 'https://example.com/se04.bin', version: [1, 0, 0] },
557
- },
558
- };
559
- const method = new CheckAllFirmwareRelease({
560
- id: 1,
561
- payload: {
562
- method: 'checkAllFirmwareRelease',
563
- platform: 'native',
564
- forceUpdateTargets: ['firmware'],
565
- },
566
- });
567
- method.init();
568
- method.device = {
569
- isProtocolV2: () => true,
570
- features: {
571
- deviceType: 'neo',
572
- serialNo: 'neo-device-id',
573
- firmwareVersion: '1.0.0',
574
- },
575
- getDeviceState: jest.fn().mockResolvedValue({
576
- identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
577
- status: { mode: 'normal' },
578
- versions: currentVersions,
579
- }),
580
- } as unknown as CheckAllFirmwareRelease['device'];
581
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
582
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
583
-
584
- await expect(method.run()).resolves.toMatchObject({
585
- targetsToUpdate: ['se01', 'se02'],
586
- firmwareUpdatePlan: {
587
- executor: 'v4',
588
- deviceModel: 'neo',
589
- platform: 'native',
590
- targetsToUpdate: ['se01', 'se02'],
591
- },
592
- });
593
- });
594
-
595
- test('rejects a forced Protocol V2 resource target without a configured archive', async () => {
596
- const method = new CheckAllFirmwareRelease({
597
- id: 1,
598
- payload: {
599
- method: 'checkAllFirmwareRelease',
600
- forceUpdateTargets: ['resource'],
601
- },
602
- });
603
- method.init();
604
- method.device = {
605
- isProtocolV2: () => true,
606
- features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
607
- getDeviceState: jest.fn().mockResolvedValue({
608
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
609
- status: { mode: 'normal' },
610
- versions: currentVersions,
611
- }),
612
- } as unknown as CheckAllFirmwareRelease['device'];
613
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
614
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
615
-
616
- await expect(method.run()).rejects.toMatchObject({
617
- params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
618
- });
619
- });
620
-
621
- test('adds a Protocol V2 resource target only when explicitly forced', async () => {
622
- const currentRelease: IFirmwareReleaseInfo = {
623
- ...release,
624
- required: false,
625
- installOrder: ['applicationP1'],
626
- components: {
627
- applicationP1: {
628
- target: 'APPLICATION_P1',
629
- url: 'https://example.com/application-p1.okpkg',
630
- version: [1, 0, 0],
631
- },
632
- },
633
- };
634
- const method = new CheckAllFirmwareRelease({
635
- id: 1,
636
- payload: {
637
- method: 'checkAllFirmwareRelease',
638
- platform: 'desktop',
639
- protocolV2ForceUpdateTargets: ['resource'],
640
- },
641
- });
642
- method.init();
643
- method.device = {
644
- isProtocolV2: () => true,
645
- features: {
646
- deviceType: 'pro2',
647
- serialNo: 'pro2-device-id',
648
- firmwareVersion: '1.0.0',
649
- },
650
- getDeviceState: jest.fn().mockResolvedValue({
651
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
652
- status: { mode: 'normal' },
653
- versions: { ...currentVersions, applicationP1: '1.0.0' },
654
- }),
655
- } as unknown as CheckAllFirmwareRelease['device'];
656
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
657
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
658
-
659
- await expect(method.run()).resolves.toMatchObject({
660
- status: 'valid',
661
- hasUpgrade: true,
662
- targetsToUpdate: ['resource'],
663
- firmwareUpdatePlan: {
664
- executor: 'v4',
665
- platform: 'desktop',
666
- artifacts: [
667
- {
668
- artifactId: 'resource:archive',
669
- target: 'resource',
670
- role: 'resourceBundle',
671
- container: 'zip',
672
- },
673
- ],
674
- targetsToUpdate: ['resource'],
675
- },
676
- });
677
- });
678
-
679
403
  test('requests and compares firmware hashes only when explicitly enabled', async () => {
680
404
  const packageSet: IFirmwareReleaseInfo = {
681
405
  ...release,
682
406
  required: false,
407
+ resourceBundles: undefined,
683
408
  installOrder: ['applicationP1'],
684
409
  components: {
685
410
  applicationP1: {
@@ -712,7 +437,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
712
437
  getCommands: () => ({ typedCall: jest.fn() }),
713
438
  } as unknown as CheckAllFirmwareRelease['device'];
714
439
  jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(packageSet);
715
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
440
+ jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(undefined);
716
441
 
717
442
  await expect(method.run()).resolves.toMatchObject({
718
443
  status: 'outdated',
@@ -724,7 +449,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
724
449
  });
725
450
 
726
451
  test.each(['bootloader', 'romloader'] as const)(
727
- 'does not read vol0 resource inventory in %s mode',
452
+ 'uses filesystem inventory in %s mode instead of forcing all resources',
728
453
  async mode => {
729
454
  const method = new CheckAllFirmwareRelease({
730
455
  id: 1,
@@ -734,7 +459,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
734
459
  },
735
460
  });
736
461
  method.init();
737
- const typedCall = jest.fn();
462
+ const typedCall = createFilesystemTypedCall();
738
463
  method.device = {
739
464
  isProtocolV2: () => true,
740
465
  features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
@@ -746,61 +471,18 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
746
471
  getCommands: () => ({ typedCall }),
747
472
  } as unknown as CheckAllFirmwareRelease['device'];
748
473
  jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
749
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
474
+ jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
750
475
 
751
476
  await expect(method.run()).resolves.toMatchObject({
752
477
  protocol: 'V2',
753
- resourceStatus: 'unknown',
754
- resourceArchive: resourceSource,
478
+ resourceStatus: 'valid',
755
479
  targetsToUpdate: ['boot', 'app_v1'],
756
480
  });
757
- expect(typedCall).not.toHaveBeenCalled();
481
+ expect(typedCall.mock.calls.some(call => call[0] === 'ResourceInventoryGet')).toBe(false);
482
+ expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileRead')).toBe(true);
758
483
  }
759
484
  );
760
485
 
761
- test('exposes resource archive availability without reporting an unconfirmed update', async () => {
762
- const currentRelease: IFirmwareReleaseInfo = {
763
- ...release,
764
- required: false,
765
- installOrder: ['applicationP1'],
766
- components: {
767
- applicationP1: {
768
- target: 'APPLICATION_P1',
769
- url: 'https://example.com/application-p1.okpkg',
770
- version: [1, 0, 0],
771
- },
772
- },
773
- };
774
- const method = new CheckAllFirmwareRelease({
775
- id: 1,
776
- payload: {
777
- method: 'checkAllFirmwareRelease',
778
- firmwareType: EFirmwareType.Universal,
779
- },
780
- });
781
- method.init();
782
- method.device = {
783
- isProtocolV2: () => true,
784
- features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
785
- getDeviceState: jest.fn().mockResolvedValue({
786
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
787
- status: { mode: 'normal' },
788
- versions: { ...currentVersions, applicationP1: '1.0.0' },
789
- }),
790
- } as unknown as CheckAllFirmwareRelease['device'];
791
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
792
- jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
793
-
794
- await expect(method.run()).resolves.toMatchObject({
795
- status: 'valid',
796
- hasUpgrade: false,
797
- resourceStatus: 'unknown',
798
- resourceArchive: resourceSource,
799
- targetsToUpdate: [],
800
- firmwareUpdatePlan: undefined,
801
- });
802
- });
803
-
804
486
  test('continues forwarding the existing public method', async () => {
805
487
  const call = jest.fn().mockResolvedValue({ success: true, payload: {} });
806
488
  const api = createCoreApi(call as CoreApi['call']) as CoreApi;
@@ -808,7 +490,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
808
490
  await api.checkAllFirmwareRelease('pro2-connect-id', {
809
491
  checkFirmwareHash: true,
810
492
  firmwareType: EFirmwareType.Universal,
811
- protocolV2ForceUpdateTargets: ['app_v1'],
812
493
  retryCount: 0,
813
494
  });
814
495
 
@@ -816,7 +497,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
816
497
  connectId: 'pro2-connect-id',
817
498
  checkFirmwareHash: true,
818
499
  firmwareType: EFirmwareType.Universal,
819
- protocolV2ForceUpdateTargets: ['app_v1'],
820
500
  retryCount: 0,
821
501
  method: 'checkAllFirmwareRelease',
822
502
  });
@@ -9,7 +9,6 @@ import {
9
9
  jest.mock('../../src/api/firmware/FirmwareUpdatePreparedPlan', () => ({
10
10
  assertFirmwareUpdatePreparedPlanBinding: jest.fn(),
11
11
  assertFirmwareUpdatePreparedPlanDeviceIdentity: jest.fn(),
12
- validateFirmwareUpdatePreparedPlan: jest.fn((preparedPlan: unknown) => preparedPlan),
13
12
  }));
14
13
 
15
14
  jest.mock('../../src/data-manager', () => ({
@@ -37,17 +36,14 @@ const createMethod = () => {
37
36
  read: jest.fn(),
38
37
  close,
39
38
  };
40
- const hostBindingGeneration = registerFirmwareUpdateHostBinding({
41
- artifactReader,
42
- preparedPlanDigest: 'a'.repeat(64),
43
- });
39
+ const hostBindingGeneration = registerFirmwareUpdateHostBinding({ artifactReader });
44
40
  const method = new DeviceUpdateBootloader({
45
41
  id: 1,
46
42
  payload: {
47
43
  method: 'deviceUpdateBootloader',
48
44
  artifact,
49
45
  hostBindingGeneration,
50
- preparedPlan: { preparedPlanDigest: 'a'.repeat(64) },
46
+ preparedPlan: {},
51
47
  },
52
48
  });
53
49
  (method as any).device = {
@@ -6,7 +6,6 @@ import {
6
6
  } from '../../src/api/firmware/FirmwareHostBinding';
7
7
 
8
8
  const createBinding = () => ({
9
- preparedPlanDigest: 'a'.repeat(64),
10
9
  artifactReader: {
11
10
  open: jest.fn(() => Promise.resolve({ readerId: 'reader-1', size: 4 })),
12
11
  read: jest.fn(() =>
@@ -68,12 +67,4 @@ describe('firmware host binding generation', () => {
68
67
  readerId: 'stale-reader',
69
68
  });
70
69
  });
71
-
72
- test('rejects a prepared plan from another host generation before opening artifacts', () => {
73
- const generation = registerFirmwareUpdateHostBinding(createBinding());
74
-
75
- expect(() => resolveFirmwareUpdateHostBinding(generation, 'b'.repeat(64))).toThrow(
76
- 'does not match the prepared plan'
77
- );
78
- });
79
70
  });