@onekeyfe/hd-core 1.2.0-alpha.89 → 1.2.0-alpha.90

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.
@@ -453,7 +453,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
453
453
  });
454
454
  });
455
455
 
456
- test('keeps exact force targets but omits a Desktop Plan without device identity', async () => {
456
+ test('builds a Desktop V4 prepared update without device identity', async () => {
457
457
  const currentRelease: IFirmwareReleaseInfo = {
458
458
  ...release,
459
459
  required: false,
@@ -490,8 +490,10 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
490
490
  jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
491
491
 
492
492
  await expect(method.run()).resolves.toMatchObject({
493
- targetsToUpdate: ['app_v1'],
494
- firmwareUpdatePlan: undefined,
493
+ firmwareUpdatePlan: {
494
+ executor: 'v4',
495
+ deviceIdentity: 'unavailable',
496
+ },
495
497
  });
496
498
  });
497
499
 
@@ -9,6 +9,7 @@ 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),
12
13
  }));
13
14
 
14
15
  jest.mock('../../src/data-manager', () => ({
@@ -46,7 +47,7 @@ const createMethod = () => {
46
47
  method: 'deviceUpdateBootloader',
47
48
  artifact,
48
49
  hostBindingGeneration,
49
- preparedPlan: {},
50
+ preparedPlan: { preparedPlanDigest: 'a'.repeat(64) },
50
51
  },
51
52
  });
52
53
  (method as any).device = {
@@ -0,0 +1,209 @@
1
+ import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
+
3
+ import FirmwareUpdateV2 from '../../src/api/FirmwareUpdateV2';
4
+ import FirmwareUpdateV3 from '../../src/api/FirmwareUpdateV3';
5
+ import DeviceUpdateBootloader from '../../src/api/device/DeviceUpdateBootloader';
6
+ import {
7
+ registerFirmwareUpdateHostBinding,
8
+ unregisterFirmwareUpdateHostBinding,
9
+ } from '../../src/api/firmware/FirmwareHostBinding';
10
+ import { prepareFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePreparedPlan';
11
+ import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
12
+
13
+ import type { FirmwareArtifactReference } from '../../src/types/api/firmwareUpdate';
14
+ import type { Features } from '../../src/types';
15
+
16
+ jest.mock('../../src/data/config', () => ({
17
+ getSDKVersion: jest.fn(() => '1.0.0'),
18
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
19
+ }));
20
+
21
+ const noUpdate = {
22
+ status: 'valid' as const,
23
+ release: undefined,
24
+ };
25
+
26
+ const createPreparedPlan = ({
27
+ executor,
28
+ target,
29
+ }: {
30
+ executor: 'v2' | 'v3';
31
+ target: 'firmware' | 'bootloader';
32
+ }) => {
33
+ const sha256 = target === 'firmware' ? 'a'.repeat(64) : 'b'.repeat(64);
34
+ const artifact: FirmwareArtifactReference = {
35
+ artifactRef: `fw:${sha256}`,
36
+ size: 4,
37
+ sha256,
38
+ };
39
+ const isV3 = executor === 'v3';
40
+ const plan = buildFirmwareUpdatePlan({
41
+ features: {
42
+ deviceType: isV3 ? EDeviceType.Pro : EDeviceType.Classic1s,
43
+ serialNo: isV3 ? 'pro-device-id' : 'classic-device-id',
44
+ firmwareVersion: '1.0.0',
45
+ bootloaderVersion: isV3 ? '2.8.0' : '1.0.0',
46
+ } as Features,
47
+ firmwareType: EFirmwareType.Universal,
48
+ platform: 'desktop',
49
+ firmware:
50
+ target === 'firmware'
51
+ ? {
52
+ status: 'outdated',
53
+ release: {
54
+ url: 'https://firmware.onekey.so/firmware.bin',
55
+ expectedSize: artifact.size,
56
+ fingerprint: artifact.sha256,
57
+ version: [3, 0, 0],
58
+ },
59
+ }
60
+ : noUpdate,
61
+ ble: noUpdate,
62
+ bootloader:
63
+ target === 'bootloader'
64
+ ? {
65
+ status: 'outdated',
66
+ shouldUpdate: true,
67
+ release: {
68
+ bootloaderResource: 'https://firmware.onekey.so/bootloader.bin',
69
+ bootloaderExpectedSize: artifact.size,
70
+ bootloaderFingerprint: artifact.sha256,
71
+ bootloaderVersion: [2, 0, 0],
72
+ },
73
+ }
74
+ : noUpdate,
75
+ });
76
+ expect(plan.executor).toBe(executor);
77
+ const preparedPlan = prepareFirmwareUpdatePlan({
78
+ plan,
79
+ leaseRef: `fwlease:${executor}:${target}`,
80
+ artifacts: [{ artifactId: target, artifact }],
81
+ });
82
+ return { artifact, preparedPlan };
83
+ };
84
+
85
+ const registerMismatchedHost = () => {
86
+ const artifactReader = {
87
+ open: jest.fn(),
88
+ read: jest.fn(),
89
+ close: jest.fn(),
90
+ };
91
+ const hostBindingGeneration = registerFirmwareUpdateHostBinding({
92
+ preparedPlanDigest: 'f'.repeat(64),
93
+ artifactReader,
94
+ });
95
+ return { artifactReader, hostBindingGeneration };
96
+ };
97
+
98
+ describe('prepared firmware host digest binding', () => {
99
+ afterEach(() => {
100
+ unregisterFirmwareUpdateHostBinding();
101
+ jest.restoreAllMocks();
102
+ });
103
+
104
+ test('FirmwareUpdateV2 rejects a host registered for another prepared plan', () => {
105
+ const { artifact, preparedPlan } = createPreparedPlan({
106
+ executor: 'v2',
107
+ target: 'firmware',
108
+ });
109
+ const { artifactReader, hostBindingGeneration } = registerMismatchedHost();
110
+ const method = new FirmwareUpdateV2({
111
+ id: 1,
112
+ payload: {
113
+ method: 'firmwareUpdateV2',
114
+ platform: 'desktop',
115
+ updateType: 'firmware',
116
+ artifact,
117
+ preparedPlan,
118
+ hostBindingGeneration,
119
+ },
120
+ });
121
+
122
+ expect(() => method.init()).toThrow('does not match the prepared plan');
123
+ expect(artifactReader.open).not.toHaveBeenCalled();
124
+ });
125
+
126
+ test('FirmwareUpdateV3 rejects a host registered for another prepared plan', () => {
127
+ const { artifact, preparedPlan } = createPreparedPlan({
128
+ executor: 'v3',
129
+ target: 'firmware',
130
+ });
131
+ const { artifactReader, hostBindingGeneration } = registerMismatchedHost();
132
+ const method = new FirmwareUpdateV3({
133
+ id: 1,
134
+ payload: {
135
+ method: 'firmwareUpdateV3',
136
+ platform: 'desktop',
137
+ artifacts: { firmware: artifact },
138
+ preparedPlan,
139
+ hostBindingGeneration,
140
+ },
141
+ });
142
+
143
+ expect(() => method.init()).toThrow('does not match the prepared plan');
144
+ expect(artifactReader.open).not.toHaveBeenCalled();
145
+ });
146
+
147
+ test('DeviceUpdateBootloader rejects a host registered for another prepared plan', async () => {
148
+ const { artifact, preparedPlan } = createPreparedPlan({
149
+ executor: 'v2',
150
+ target: 'bootloader',
151
+ });
152
+ const { artifactReader, hostBindingGeneration } = registerMismatchedHost();
153
+ const method = new DeviceUpdateBootloader({
154
+ id: 1,
155
+ payload: {
156
+ method: 'deviceUpdateBootloader',
157
+ artifact,
158
+ preparedPlan,
159
+ hostBindingGeneration,
160
+ },
161
+ });
162
+ method.device = {
163
+ features: {
164
+ deviceType: EDeviceType.Classic1s,
165
+ serialNo: 'classic-device-id',
166
+ },
167
+ } as any;
168
+
169
+ await expect(method.run()).rejects.toThrow('does not match the prepared plan');
170
+ expect(artifactReader.open).not.toHaveBeenCalled();
171
+ });
172
+
173
+ test('keeps non-prepared direct binary calls on the legacy paths', async () => {
174
+ const v2 = new FirmwareUpdateV2({
175
+ id: 1,
176
+ payload: {
177
+ method: 'firmwareUpdateV2',
178
+ platform: 'desktop',
179
+ updateType: 'firmware',
180
+ binary: new ArrayBuffer(4),
181
+ },
182
+ });
183
+ const v3 = new FirmwareUpdateV3({
184
+ id: 2,
185
+ payload: {
186
+ method: 'firmwareUpdateV3',
187
+ platform: 'desktop',
188
+ firmwareBinary: new ArrayBuffer(4),
189
+ },
190
+ });
191
+ const bootloader = new DeviceUpdateBootloader({
192
+ id: 3,
193
+ payload: {
194
+ method: 'deviceUpdateBootloader',
195
+ binary: new ArrayBuffer(4),
196
+ },
197
+ });
198
+ bootloader.device = {
199
+ features: {},
200
+ getCurrentDeviceType: () => EDeviceType.Touch,
201
+ getCurrentFirmwareType: () => EFirmwareType.Universal,
202
+ } as any;
203
+ jest.spyOn(bootloader, 'updateTouchBootloader').mockResolvedValue(true);
204
+
205
+ expect(() => v2.init()).not.toThrow();
206
+ expect(() => v3.init()).not.toThrow();
207
+ await expect(bootloader.run()).resolves.toBe(true);
208
+ });
209
+ });
@@ -1,6 +1,10 @@
1
1
  import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
4
+ import {
5
+ assertFirmwareUpdatePreparedPlanDeviceIdentity,
6
+ prepareFirmwareUpdatePlan,
7
+ } from '../../src/api/firmware/FirmwareUpdatePreparedPlan';
4
8
 
5
9
  import type { Features } from '../../src/types';
6
10
 
@@ -362,6 +366,71 @@ describe('buildFirmwareUpdatePlan', () => {
362
366
  ).toThrow('requires a stable device identity');
363
367
  });
364
368
 
369
+ test('allows an identity-less Protocol V2 device while retaining the model binding', () => {
370
+ const features = createFeatures({
371
+ deviceType: EDeviceType.Pro2,
372
+ });
373
+ delete (features as Partial<Features>).serialNo;
374
+
375
+ const plan = buildFirmwareUpdatePlan({
376
+ features,
377
+ firmwareType: EFirmwareType.Universal,
378
+ platform: 'desktop',
379
+ firmware: {
380
+ status: 'outdated',
381
+ release: {
382
+ components: {
383
+ applicationP1: {
384
+ target: 'APPLICATION_P1',
385
+ url: 'https://firmware.onekey.so/pro2/application-p1.bin',
386
+ expectedSize: 1024,
387
+ fingerprint: '1111111111111111111111111111111111111111111111111111111111111111',
388
+ },
389
+ },
390
+ },
391
+ },
392
+ ble: noUpdate,
393
+ bootloader: noUpdate,
394
+ });
395
+
396
+ expect(plan).toMatchObject({
397
+ executor: 'v4',
398
+ deviceIdentity: 'unavailable',
399
+ deviceModel: String(EDeviceType.Pro2),
400
+ });
401
+
402
+ const preparedPlan = prepareFirmwareUpdatePlan({
403
+ plan,
404
+ leaseRef: 'fwlease:00000000-0000-4000-8000-000000000004',
405
+ artifacts: [
406
+ {
407
+ artifactId: 'component:app_v1',
408
+ artifact: {
409
+ artifactRef: `fw:${'1'.repeat(64)}`,
410
+ size: 1024,
411
+ sha256: '1'.repeat(64),
412
+ },
413
+ },
414
+ ],
415
+ });
416
+ expect(() =>
417
+ assertFirmwareUpdatePreparedPlanDeviceIdentity({
418
+ preparedPlan,
419
+ deviceIdentity: undefined,
420
+ bootloaderMode: false,
421
+ deviceModel: String(EDeviceType.Pro2),
422
+ })
423
+ ).not.toThrow();
424
+ expect(() =>
425
+ assertFirmwareUpdatePreparedPlanDeviceIdentity({
426
+ preparedPlan,
427
+ deviceIdentity: undefined,
428
+ bootloaderMode: false,
429
+ deviceModel: String(EDeviceType.Neo),
430
+ })
431
+ ).toThrow();
432
+ });
433
+
365
434
  test('maps the Pro2 component order without downloading artifacts', () => {
366
435
  const plan = buildFirmwareUpdatePlan({
367
436
  features: createFeatures({ deviceType: EDeviceType.Pro2 }),
@@ -1 +1 @@
1
- {"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CA0H5B"}
1
+ {"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CAsH5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyB1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;IAmFJ,cAAc,YAAa,MAAM,UAS/B;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YA8FvC,4BAA4B;IAyB1C,qBAAqB;IAUrB,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAc1C,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,YAAY,EAAE,aAAa;IAwBtF,GAAG;CAgQV"}
1
+ {"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA0B1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;IAuFJ,cAAc,YAAa,MAAM,UAS/B;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YA8FvC,4BAA4B;IAyB1C,qBAAqB;IAUrB,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAc1C,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,YAAY,EAAE,aAAa;IAwBtF,GAAG;CAgQV"}
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV3.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV3.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAY/E,OAAO,KAAK,EAEV,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAMnE,eAAO,MAAM,gCAAgC,UAAU,CAAC;AAaxD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA4B;IAEnD,IAAI;IAmFE,GAAG;;;;;YAQK,aAAa;IA6D3B,OAAO,CAAC,wBAAwB;YAiBlB,kBAAkB;YAelB,oBAAoB;IAKlC,OAAO,CAAC,wBAAwB;YAgBlB,oBAAoB;YA2DpB,uBAAuB;YAuBvB,4BAA4B;YA+E5B,aAAa;IAyN3B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,sCAAsC;IAexC,sBAAsB,CAAC,OAAO,EAAE,MAAM;CA+E7C"}
1
+ {"version":3,"file":"FirmwareUpdateV3.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV3.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAa/E,OAAO,KAAK,EAEV,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAMnE,eAAO,MAAM,gCAAgC,UAAU,CAAC;AAaxD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe,CAA4B;IAEnD,IAAI;IAyFE,GAAG;;;;;YAQK,aAAa;IA6D3B,OAAO,CAAC,wBAAwB;YAiBlB,kBAAkB;YAelB,oBAAoB;IAKlC,OAAO,CAAC,wBAAwB;YAgBlB,oBAAoB;YA2DpB,uBAAuB;YAuBvB,4BAA4B;YA+E5B,aAAa;IAyN3B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,sCAAsC;IAexC,sBAAsB,CAAC,OAAO,EAAE,MAAM;CA+E7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceUpdateBootloader.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUpdateBootloader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAgBhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,wBAAwB,CAAC,GAAG,CAAC;IAC/E,IAAI;IAOE,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAoBtE,2CAA2C,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB;IAcvF,qBAAqB,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,GACvB,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,MAAM,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IA0EK,GAAG;CA0EV"}
1
+ {"version":3,"file":"DeviceUpdateBootloader.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUpdateBootloader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAiBhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,wBAAwB,CAAC,GAAG,CAAC;IAC/E,IAAI;IAOE,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAoBtE,2CAA2C,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB;IAcvF,qBAAqB,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,GACvB,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,MAAM,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IA0EK,GAAG;CAgFV"}
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdatePlan.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdatePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAU5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EACV,kBAAkB,EAElB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAEvE,KAAK,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;AAEjF,KAAK,aAAa,GAAG;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA+GF,eAAO,MAAM,4BAA4B,UAAW,OAAO,KAAG,MAG3D,CAAC;AAkBJ,eAAO,MAAM,sCAAsC,UAC1C,OAAO,KACb,6BAA6B,EAa/B,CAAC;AAEF,eAAO,MAAM,uCAAuC,UAC3C,OAAO,KACb,sBAAsB,EAaxB,CAAC;AAuBF,eAAO,MAAM,4BAA4B,+BAavC,CAAC;AAEH,eAAO,MAAM,0BAA0B,aAOrC,CAAC;AAYH,eAAO,MAAM,wBAAwB,UAAW,OAAO,KAAG,kBAyHzD,CAAC;AAuPF,MAAM,MAAM,yCAAyC,GAAG;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;IAC1D,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,sCAAsC;cAMvC,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;eACrB,yCAAyC,EAAE;MACpD,kBAmBH,CAAC;AAEF,eAAO,MAAM,iCAAiC;cASlC,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;aACvB,aAAa,GAAG,SAAS;qBACjB,SAAS,sBAAsB,EAAE;;qBAEjC,yBAAyB,GAAG,SAAS;MACpD,kBAgEH,CAAC;AAEF,eAAO,MAAM,uBAAuB;cASxB,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;cACtB,gBAAgB;SACrB,gBAAgB;;;MAGnB,kBAwIH,CAAC"}
1
+ {"version":3,"file":"FirmwareUpdatePlan.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdatePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAU5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EACV,kBAAkB,EAElB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAEvE,KAAK,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;AAEjF,KAAK,aAAa,GAAG;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA+GF,eAAO,MAAM,4BAA4B,UAAW,OAAO,KAAG,MAG3D,CAAC;AAkBJ,eAAO,MAAM,sCAAsC,UAC1C,OAAO,KACb,6BAA6B,EAa/B,CAAC;AAEF,eAAO,MAAM,uCAAuC,UAC3C,OAAO,KACb,sBAAsB,EAaxB,CAAC;AAuBF,eAAO,MAAM,4BAA4B,+BAavC,CAAC;AAEH,eAAO,MAAM,0BAA0B,aAOrC,CAAC;AAYH,eAAO,MAAM,wBAAwB,UAAW,OAAO,KAAG,kBAuHzD,CAAC;AAqPF,MAAM,MAAM,yCAAyC,GAAG;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;IAC1D,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,sCAAsC;cAMvC,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;eACrB,yCAAyC,EAAE;MACpD,kBAmBH,CAAC;AAEF,eAAO,MAAM,iCAAiC;cASlC,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;aACvB,aAAa,GAAG,SAAS;qBACjB,SAAS,sBAAsB,EAAE;;qBAEjC,yBAAyB,GAAG,SAAS;MACpD,kBAgEH,CAAC;AAEF,eAAO,MAAM,uBAAuB;cASxB,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;cACtB,gBAAgB;SACrB,gBAAgB;;;MAGnB,kBAwIH,CAAC"}
package/dist/index.js CHANGED
@@ -754,7 +754,7 @@ const assertFirmwareUpdatePlan = (value) => {
754
754
  plan.targetsToUpdate.some(target => legacyOnlyTargets.has(target))) ||
755
755
  (plan.artifacts.length > 0 &&
756
756
  (plan.platform === 'native' || plan.platform === 'desktop') &&
757
- plan.executor !== 'v2' &&
757
+ plan.executor === 'v3' &&
758
758
  plan.deviceIdentity === 'unavailable')) {
759
759
  return planError('Firmware update plan executor contract is invalid');
760
760
  }
@@ -879,10 +879,11 @@ const finalizeFirmwareUpdatePlan = ({ features, firmwareType, platform, artifact
879
879
  const bootloaderMode = resolveDeviceBootloaderMode(features);
880
880
  const reportedIdentity = getDeviceUUID(features);
881
881
  const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
882
+ const allowsUnavailableIdentity = (bootloaderMode && executor === 'v2') || executor === 'v4';
882
883
  if (artifacts.length > 0 &&
883
884
  (platform === 'native' || platform === 'desktop') &&
884
885
  !deviceIdentity &&
885
- !(bootloaderMode && executor === 'v2')) {
886
+ !allowsUnavailableIdentity) {
886
887
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Prepared firmware update requires a stable device identity', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
887
888
  }
888
889
  const planWithoutDigest = {
@@ -1294,7 +1295,7 @@ const assertFirmwareUpdatePreparedPlanDeviceIdentity = ({ preparedPlan: value, d
1294
1295
  }
1295
1296
  const pinnedIdentity = degradedPlanIdentityPins.get(preparedPlan.leaseRef);
1296
1297
  if (!deviceIdentity) {
1297
- if (bootloaderMode !== true) {
1298
+ if (preparedPlan.executor !== 'v4' && bootloaderMode !== true) {
1298
1299
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
1299
1300
  }
1300
1301
  return preparedPlan;
@@ -47804,32 +47805,30 @@ class CheckAllFirmwareRelease extends BaseMethod {
47804
47805
  ...(forceResourceUpdate ? ['resource'] : []),
47805
47806
  ]));
47806
47807
  let firmwareUpdatePlan;
47808
+ const shouldBuildFirmwareUpdatePlan = targetsToUpdate.length > 0;
47809
+ const requestedPlatform = platform !== null && platform !== void 0 ? platform : 'web';
47810
+ const requiresPreparedPlan = shouldBuildFirmwareUpdatePlan &&
47811
+ (requestedPlatform === 'native' || requestedPlatform === 'desktop');
47807
47812
  try {
47808
- const shouldBuildFirmwareUpdatePlan = targetsToUpdate.length > 0;
47809
- const requestedPlatform = platform !== null && platform !== void 0 ? platform : 'web';
47810
- const requiresDeviceIdentity = requestedPlatform === 'native' || requestedPlatform === 'desktop';
47811
- const canBindPreparedPlan = !requiresDeviceIdentity || !!getDeviceSerialNo(features);
47812
47813
  if (shouldBuildFirmwareUpdatePlan) {
47813
47814
  const validatedPlan = buildProtocolV2FirmwareUpdatePlan({
47814
47815
  features,
47815
47816
  firmwareType,
47816
- platform: canBindPreparedPlan ? requestedPlatform : 'web',
47817
+ platform: requestedPlatform,
47817
47818
  release,
47818
47819
  targetsToUpdate,
47819
47820
  forceUpdateTargets: validatedForceUpdateTargets,
47820
47821
  resourceArchive: resourceSource,
47821
47822
  });
47822
- firmwareUpdatePlan = canBindPreparedPlan ? validatedPlan : undefined;
47823
- if (!canBindPreparedPlan) {
47824
- Log$c.warn('[CheckAllFirmwareRelease] Protocol V2 device identity is unavailable; using the release result without a prepared Plan');
47825
- }
47823
+ firmwareUpdatePlan = validatedPlan;
47826
47824
  }
47827
47825
  else {
47828
47826
  firmwareUpdatePlan = undefined;
47829
47827
  }
47830
47828
  }
47831
47829
  catch (error) {
47832
- if (validatedForceUpdateTargets.length > 0 ||
47830
+ if (requiresPreparedPlan ||
47831
+ validatedForceUpdateTargets.length > 0 ||
47833
47832
  validatedProtocolV2ForceUpdateTargets.length > 0 ||
47834
47833
  !(error instanceof hdShared.HardwareError) ||
47835
47834
  ((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) !== 'FirmwarePlanInvalid') {
@@ -49783,19 +49782,22 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
49783
49782
  const { device } = this;
49784
49783
  const { features } = device;
49785
49784
  const payload = this.payload;
49786
- const hostBinding = payload.artifact
49787
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
49785
+ const preparedPlan = payload.artifact
49786
+ ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
49787
+ : undefined;
49788
+ const hostBinding = preparedPlan
49789
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest)
49788
49790
  : undefined;
49789
49791
  const executionParams = Object.assign(Object.assign({}, payload), { artifactReader: (_a = hostBinding === null || hostBinding === void 0 ? void 0 : hostBinding.artifactReader) !== null && _a !== void 0 ? _a : payload.artifactReader });
49790
49792
  if (payload.artifact) {
49791
49793
  assertFirmwareUpdatePreparedPlanDeviceIdentity({
49792
- preparedPlan: payload.preparedPlan,
49794
+ preparedPlan,
49793
49795
  deviceIdentity: getDeviceUUID(features) || undefined,
49794
49796
  bootloaderMode: resolveDeviceBootloaderMode(features),
49795
49797
  deviceModel: String(getDeviceType(features)),
49796
49798
  });
49797
49799
  assertFirmwareUpdatePreparedPlanBinding({
49798
- preparedPlan: payload.preparedPlan,
49800
+ preparedPlan,
49799
49801
  executor: 'v2',
49800
49802
  scopeTargets: ['bootloader'],
49801
49803
  bindings: [
@@ -50202,7 +50204,8 @@ class FirmwareUpdateV2 extends BaseMethod {
50202
50204
  this.params = Object.assign(Object.assign({}, this.params), { binary: payload.binary });
50203
50205
  }
50204
50206
  if ('artifact' in payload) {
50205
- const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration);
50207
+ const preparedPlan = validateFirmwareUpdatePreparedPlan(payload.preparedPlan);
50208
+ const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest);
50206
50209
  const target = payload.isUpdateBootloader ? 'bootloader' : payload.updateType;
50207
50210
  const resourceBindings = ((_a = payload.resourceEntries) !== null && _a !== void 0 ? _a : []).map((entry) => ({
50208
50211
  target: 'resource',
@@ -50210,13 +50213,13 @@ class FirmwareUpdateV2 extends BaseMethod {
50210
50213
  artifact: entry.artifact,
50211
50214
  }));
50212
50215
  assertFirmwareUpdatePreparedPlanBinding({
50213
- preparedPlan: payload.preparedPlan,
50216
+ preparedPlan,
50214
50217
  executor: 'v2',
50215
50218
  platform: payload.platform,
50216
50219
  scopeTargets: [target, ...(target === 'firmware' ? ['resource'] : [])],
50217
50220
  bindings: [{ target, artifact: payload.artifact }, ...resourceBindings],
50218
50221
  });
50219
- this.params = Object.assign(Object.assign({}, this.params), { preparedPlan: payload.preparedPlan, artifact: payload.artifact, resourceEntries: payload.resourceEntries, artifactReader: hostBinding.artifactReader });
50222
+ this.params = Object.assign(Object.assign({}, this.params), { preparedPlan, artifact: payload.artifact, resourceEntries: payload.resourceEntries, artifactReader: hostBinding.artifactReader });
50220
50223
  }
50221
50224
  }
50222
50225
  _promptDeviceInBootloaderForWebDevice() {
@@ -50579,12 +50582,15 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50579
50582
  { name: 'firmwareType', type: 'string' },
50580
50583
  { name: 'platform', type: 'string' },
50581
50584
  ]);
50582
- const hostBinding = payload.artifacts || payload.preparedPlan
50583
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
50585
+ const preparedPlan = payload.artifacts || payload.preparedPlan
50586
+ ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
50587
+ : undefined;
50588
+ const hostBinding = preparedPlan
50589
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest)
50584
50590
  : undefined;
50585
50591
  if (hostBinding) {
50586
50592
  assertFirmwareUpdatePreparedPlanBinding({
50587
- preparedPlan: payload.preparedPlan,
50593
+ preparedPlan,
50588
50594
  executor: 'v3',
50589
50595
  platform: payload.platform,
50590
50596
  scopeTargets: ['bootloader', 'firmware', 'resource', 'ble'],
@@ -50622,7 +50628,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50622
50628
  });
50623
50629
  }
50624
50630
  this.params = {
50625
- preparedPlan: payload.preparedPlan,
50631
+ preparedPlan,
50626
50632
  bleBinary: payload.bleBinary,
50627
50633
  firmwareBinary: payload.firmwareBinary,
50628
50634
  forcedUpdateRes: payload.forcedUpdateRes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.89",
3
+ "version": "1.2.0-alpha.90",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.89",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.89",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.90",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.90",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "bytebuffer": "^5.0.1",
@@ -44,5 +44,5 @@
44
44
  "@types/w3c-web-usb": "^1.0.10",
45
45
  "@types/web-bluetooth": "^0.0.21"
46
46
  },
47
- "gitHead": "4730d9cdba7270cd9aef237a9076b36dd89f37c1"
47
+ "gitHead": "e8271225634f3058498af8beee06d9de705b6710"
48
48
  }
@@ -28,7 +28,6 @@ import { getBridgeReleaseInfo } from '../utils/bridgeUpdate';
28
28
  import {
29
29
  LoggerNames,
30
30
  getDeviceFirmwareVersion,
31
- getDeviceSerialNo,
32
31
  getDeviceType,
33
32
  getFirmwareType,
34
33
  getLogger,
@@ -437,33 +436,29 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
437
436
  ])
438
437
  );
439
438
  let firmwareUpdatePlan: FirmwareUpdatePlan | undefined;
439
+ const shouldBuildFirmwareUpdatePlan = targetsToUpdate.length > 0;
440
+ const requestedPlatform = platform ?? 'web';
441
+ const requiresPreparedPlan =
442
+ shouldBuildFirmwareUpdatePlan &&
443
+ (requestedPlatform === 'native' || requestedPlatform === 'desktop');
440
444
  try {
441
- const shouldBuildFirmwareUpdatePlan = targetsToUpdate.length > 0;
442
- const requestedPlatform = platform ?? 'web';
443
- const requiresDeviceIdentity =
444
- requestedPlatform === 'native' || requestedPlatform === 'desktop';
445
- const canBindPreparedPlan = !requiresDeviceIdentity || !!getDeviceSerialNo(features);
446
445
  if (shouldBuildFirmwareUpdatePlan) {
447
446
  const validatedPlan = buildProtocolV2FirmwareUpdatePlan({
448
447
  features,
449
448
  firmwareType,
450
- platform: canBindPreparedPlan ? requestedPlatform : 'web',
449
+ platform: requestedPlatform,
451
450
  release,
452
451
  targetsToUpdate,
453
452
  forceUpdateTargets: validatedForceUpdateTargets,
454
453
  resourceArchive: resourceSource,
455
454
  });
456
- firmwareUpdatePlan = canBindPreparedPlan ? validatedPlan : undefined;
457
- if (!canBindPreparedPlan) {
458
- Log.warn(
459
- '[CheckAllFirmwareRelease] Protocol V2 device identity is unavailable; using the release result without a prepared Plan'
460
- );
461
- }
455
+ firmwareUpdatePlan = validatedPlan;
462
456
  } else {
463
457
  firmwareUpdatePlan = undefined;
464
458
  }
465
459
  } catch (error) {
466
460
  if (
461
+ requiresPreparedPlan ||
467
462
  validatedForceUpdateTargets.length > 0 ||
468
463
  validatedProtocolV2ForceUpdateTargets.length > 0 ||
469
464
  !(error instanceof HardwareError) ||
@@ -33,6 +33,7 @@ import {
33
33
  assertFirmwareUpdatePreparedPlanBinding,
34
34
  assertFirmwareUpdatePreparedPlanDeviceIdentity,
35
35
  getFirmwareUpdateResourceName,
36
+ validateFirmwareUpdatePreparedPlan,
36
37
  } from './firmware/FirmwareUpdatePreparedPlan';
37
38
 
38
39
  import type { Features, KnownDevice } from '../types';
@@ -200,7 +201,11 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
200
201
  }
201
202
 
202
203
  if ('artifact' in payload) {
203
- const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration);
204
+ const preparedPlan = validateFirmwareUpdatePreparedPlan(payload.preparedPlan);
205
+ const hostBinding = resolveFirmwareUpdateHostBinding(
206
+ payload.hostBindingGeneration,
207
+ preparedPlan.preparedPlanDigest
208
+ );
204
209
  const target = payload.isUpdateBootloader ? 'bootloader' : payload.updateType;
205
210
  const resourceBindings = (payload.resourceEntries ?? []).map(
206
211
  (entry: { entryName: string; artifact: FirmwareArtifactReference }) => ({
@@ -210,7 +215,7 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
210
215
  })
211
216
  );
212
217
  assertFirmwareUpdatePreparedPlanBinding({
213
- preparedPlan: payload.preparedPlan,
218
+ preparedPlan,
214
219
  executor: 'v2',
215
220
  platform: payload.platform,
216
221
  scopeTargets: [target, ...(target === 'firmware' ? (['resource'] as const) : [])],
@@ -218,7 +223,7 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
218
223
  });
219
224
  this.params = {
220
225
  ...this.params,
221
- preparedPlan: payload.preparedPlan,
226
+ preparedPlan,
222
227
  artifact: payload.artifact,
223
228
  resourceEntries: payload.resourceEntries,
224
229
  artifactReader: hostBinding.artifactReader,
@@ -25,6 +25,7 @@ import {
25
25
  assertFirmwareUpdatePreparedPlanBinding,
26
26
  assertFirmwareUpdatePreparedPlanDeviceIdentity,
27
27
  getFirmwareUpdateResourceName,
28
+ validateFirmwareUpdatePreparedPlan,
28
29
  } from './firmware/FirmwareUpdatePreparedPlan';
29
30
 
30
31
  import type {
@@ -77,13 +78,19 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
77
78
  { name: 'firmwareType', type: 'string' },
78
79
  { name: 'platform', type: 'string' },
79
80
  ]);
80
- const hostBinding =
81
+ const preparedPlan =
81
82
  payload.artifacts || payload.preparedPlan
82
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
83
+ ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
83
84
  : undefined;
85
+ const hostBinding = preparedPlan
86
+ ? resolveFirmwareUpdateHostBinding(
87
+ payload.hostBindingGeneration,
88
+ preparedPlan.preparedPlanDigest
89
+ )
90
+ : undefined;
84
91
  if (hostBinding) {
85
92
  assertFirmwareUpdatePreparedPlanBinding({
86
- preparedPlan: payload.preparedPlan,
93
+ preparedPlan,
87
94
  executor: 'v3',
88
95
  platform: payload.platform,
89
96
  scopeTargets: ['bootloader', 'firmware', 'resource', 'ble'],
@@ -124,7 +131,7 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
124
131
  }
125
132
 
126
133
  this.params = {
127
- preparedPlan: payload.preparedPlan,
134
+ preparedPlan,
128
135
  bleBinary: payload.bleBinary,
129
136
  firmwareBinary: payload.firmwareBinary,
130
137
  forcedUpdateRes: payload.forcedUpdateRes,
@@ -14,6 +14,7 @@ import { resolveFirmwareUpdateHostBinding } from '../firmware/FirmwareHostBindin
14
14
  import {
15
15
  assertFirmwareUpdatePreparedPlanBinding,
16
16
  assertFirmwareUpdatePreparedPlanDeviceIdentity,
17
+ validateFirmwareUpdatePreparedPlan,
17
18
  } from '../firmware/FirmwareUpdatePreparedPlan';
18
19
  import { getDeviceType, getDeviceUUID } from '../../utils';
19
20
  import { resolveDeviceBootloaderMode } from '../../utils/deviceFeaturesCompat';
@@ -157,8 +158,14 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
157
158
  const { features } = device;
158
159
 
159
160
  const payload = this.payload as DeviceUpdateBootloaderParams;
160
- const hostBinding = payload.artifact
161
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
161
+ const preparedPlan = payload.artifact
162
+ ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
163
+ : undefined;
164
+ const hostBinding = preparedPlan
165
+ ? resolveFirmwareUpdateHostBinding(
166
+ payload.hostBindingGeneration,
167
+ preparedPlan.preparedPlanDigest
168
+ )
162
169
  : undefined;
163
170
  const executionParams = {
164
171
  ...payload,
@@ -166,13 +173,13 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
166
173
  };
167
174
  if (payload.artifact) {
168
175
  assertFirmwareUpdatePreparedPlanDeviceIdentity({
169
- preparedPlan: payload.preparedPlan,
176
+ preparedPlan,
170
177
  deviceIdentity: getDeviceUUID(features) || undefined,
171
178
  bootloaderMode: resolveDeviceBootloaderMode(features),
172
179
  deviceModel: String(getDeviceType(features)),
173
180
  });
174
181
  assertFirmwareUpdatePreparedPlanBinding({
175
- preparedPlan: payload.preparedPlan,
182
+ preparedPlan,
176
183
  executor: 'v2',
177
184
  scopeTargets: ['bootloader'],
178
185
  bindings: [
@@ -373,13 +373,11 @@ export const assertFirmwareUpdatePlan = (value: unknown): FirmwareUpdatePlan =>
373
373
  plan.targetsToUpdate.some(target =>
374
374
  legacyOnlyTargets.has(target as FirmwareUpdatePlanTarget)
375
375
  )) ||
376
- // Only executor v2 services identity-less bootloader recovery (classic family);
377
- // Pro (v3) and Pro2 (v4) report a serial even in bootloader mode, so their plans
378
- // must always carry a real identity. Degraded v2 plans are bound to the live
379
- // device at install time instead.
376
+ // V2 仅在 bootloader 恢复时允许缺少身份;V4 设备在尚未写入序列号时也可升级。
377
+ // 这类 Plan 仍通过设备型号、目标、工件摘要与 preparedPlanDigest 进行约束。
380
378
  (plan.artifacts.length > 0 &&
381
379
  (plan.platform === 'native' || plan.platform === 'desktop') &&
382
- plan.executor !== 'v2' &&
380
+ plan.executor === 'v3' &&
383
381
  plan.deviceIdentity === 'unavailable')
384
382
  ) {
385
383
  return planError('Firmware update plan executor contract is invalid');
@@ -603,16 +601,14 @@ const finalizeFirmwareUpdatePlan = ({
603
601
  // serial must never be able to collide with it.
604
602
  const reportedIdentity = getDeviceUUID(features);
605
603
  const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
606
- // Bootloader-mode classic-family devices (executor v2, e.g. classic1s) cannot report
607
- // a serial number, so their recovery plans fall back to the degraded 'unavailable'
608
- // identity. Binding is then enforced against the live device at install time instead
609
- // (assertFirmwareUpdatePreparedPlanDeviceIdentity), and plan integrity by the digest.
610
- // Pro (v3), Pro2, and Neo (v4) report a serial even in loader mode and stay strict.
604
+ // Classic 系列仅在 bootloader 恢复时允许缺少身份;部分尚未完成产线写号的
605
+ // Pro2/Neo(V4)在正常模式下也可能没有序列号,因此允许使用降级身份。
606
+ const allowsUnavailableIdentity = (bootloaderMode && executor === 'v2') || executor === 'v4';
611
607
  if (
612
608
  artifacts.length > 0 &&
613
609
  (platform === 'native' || platform === 'desktop') &&
614
610
  !deviceIdentity &&
615
- !(bootloaderMode && executor === 'v2')
611
+ !allowsUnavailableIdentity
616
612
  ) {
617
613
  throw ERRORS.TypedError(
618
614
  HardwareErrorCode.RuntimeError,
@@ -349,8 +349,8 @@ export const assertFirmwareUpdatePreparedPlanDeviceIdentity = ({
349
349
  }
350
350
  const pinnedIdentity = degradedPlanIdentityPins.get(preparedPlan.leaseRef);
351
351
  if (!deviceIdentity) {
352
- // Still identity-less: only legitimate while the device sits in bootloader.
353
- if (bootloaderMode !== true) {
352
+ // V4 设备可能尚未写入序列号;V2 则只允许 bootloader 恢复流程缺少身份。
353
+ if (preparedPlan.executor !== 'v4' && bootloaderMode !== true) {
354
354
  throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
355
355
  }
356
356
  return preparedPlan;