From 4ea919b834a792e0fef28d00895c16e7d64ca9a3 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 10:10:41 +0100 Subject: [PATCH 01/16] chore(ai-review): record design forecast --- ...-1117-tpm-blacklisted-pr-66d786804bbd.json | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json new file mode 100644 index 0000000000..fe0124bdab --- /dev/null +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -0,0 +1,30 @@ +{ + "disposition": "PATCH", + "expected_structural_delta": "Add no production modules, owners, dependencies, representations, or pass-through hops. Extend one existing Registration predicate, the existing PHP state fallback, and the existing Registration test file with focused positive and negative cases.", + "minimum_design": "Extend the existing Registration eligibility predicate to require normal EBLACKLISTED state, a key file, a flash boot device, a usable TPM GUID, and a different registered TPM GUID. Reuse the existing PHP state payload fallback and Account replacement operation.", + "outcome": "When the current boot device is a blacklisted flash, a usable new TPM is detected, and the installed key is registered to a different old TPM GUID, Registration shows the existing TPM key-replacement action.", + "reuse_decisions": [ + { + "decision": "extend", + "name": "Existing Registration TPM replacement action", + "rationale": "The component already owns the TPM eligibility predicate, button, payload, and Account action. Extending it keeps one customer-facing action and one effect path." + }, + { + "decision": "extend", + "name": "Existing server state representation", + "rationale": "The existing server store already exposes the boot, registered, and TPM identifiers. The PHP fallback supplies the missing TPM identifier." + }, + { + "decision": "reuse", + "name": "Account TPM replacement operation", + "rationale": "The existing Account replaceTpm operation already handles the replacement request. No provider operation is added." + }, + { + "decision": "not applicable", + "name": "Other blacklisted states and Core UI", + "rationale": "The ticket concerns normal EBLACKLISTED with a blacklisted flash and an old-TPM/new-TPM mismatch. Other blacklisted state codes and the separate Core UI are outside this causal path." + } + ], + "schema": "limetech.ai-review-marker.v2", + "stage": "forecast" +} From 20bc0b337851d88e54506f1352b59dc24dd7c7f1 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 10:09:48 +0100 Subject: [PATCH 02/16] fix(registration): expose TPM replacement for blacklisted flash --- .../dynamix.my.servers/include/state.php | 1 + web/__test__/components/Registration.test.ts | 72 +++++++++++++++++++ .../components/Registration.standalone.vue | 18 ++++- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/state.php b/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/state.php index 53050ebab7..8f47815cec 100644 --- a/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/state.php +++ b/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/state.php @@ -289,6 +289,7 @@ public function getServerState() "flashVendor" => $this->var['flashVendor'], "flashBackupActivated" => $this->flashBackupActivated, "guid" => $this->var['flashGUID'], + "tpmGuid" => $this->var['tpmGUID'] ?? '', "hasRemoteApikey" => $this->hasRemoteApikey, "internalPort" => _var($_SERVER, 'SERVER_PORT'), "keyfile" => $this->keyfileBase64UrlSafe, diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index 788542a161..0a87a3b12f 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -366,6 +366,78 @@ describe('Registration.standalone.vue', () => { expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(true); }); + it('shows Move License to TPM when the boot flash is blacklisted but TPM licensing is available', async () => { + serverStore.state = 'EBLACKLISTED'; + serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.regGuid = '01-OLD-TPM-GUID-1234567890'; + serverStore.tpmGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.keyfile = 'keyfile-present'; + + await wrapper.vm.$nextTick(); + + const moveButton = wrapper.find('[data-testid="move-license-to-tpm"]'); + + expect(moveButton.exists()).toBe(true); + expect(moveButton.attributes('disabled')).toBeUndefined(); + expect(wrapper.text()).toContain('Blacklisted boot device GUID'); + expect(wrapper.find('[data-testid="key-actions"]').exists()).toBe(false); + + await moveButton.trigger('click'); + + expect(accountStore.replaceTpm).toHaveBeenCalled(); + }); + + it('does not show Move License to TPM for invalid blacklisted states', async () => { + serverStore.state = 'EBLACKLISTED1'; + serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.tpmGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.keyfile = 'keyfile-present'; + + await wrapper.vm.$nextTick(); + + expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false); + }); + + it('does not show Move License to TPM for a blacklisted boot flash without a key file', async () => { + serverStore.state = 'EBLACKLISTED'; + serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.tpmGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.keyfile = ''; + + await wrapper.vm.$nextTick(); + + expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false); + }); + + it('does not show Move License to TPM when the blacklisted flash is still the registered license device', async () => { + serverStore.state = 'EBLACKLISTED'; + serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.regGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.tpmGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.keyfile = 'keyfile-present'; + + await wrapper.vm.$nextTick(); + + expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false); + }); + + it('does not show Move License to TPM when the key is already registered to the detected TPM', async () => { + serverStore.state = 'EBLACKLISTED'; + serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; + serverStore.regGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.tpmGuid = '01-V35H8S0L1QHK1SBG1XHXJNH7'; + serverStore.keyfile = 'keyfile-present'; + + await wrapper.vm.$nextTick(); + + expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false); + }); + it('triggers the TPM replacement action when Move License to TPM is clicked', async () => { serverStore.state = 'PRO'; serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; diff --git a/web/src/components/Registration.standalone.vue b/web/src/components/Registration.standalone.vue index d68331d4d2..6e35265c2c 100644 --- a/web/src/components/Registration.standalone.vue +++ b/web/src/components/Registration.standalone.vue @@ -49,6 +49,7 @@ const { flashProduct, flashVendor, guid, + keyfile, keyActions, computedRegDevs, regGuid, @@ -128,8 +129,21 @@ const showPartnerActivationCode = computed(() => { (currentState === 'ENOKEYFILE' || currentState === 'TRIAL' || currentState === 'EEXPIRED') ); }); +const hasBlacklistedTpmLicenseMismatch = computed( + (): boolean => + state.value === 'EBLACKLISTED' && + Boolean( + keyfile.value && + regGuid.value.startsWith('01-') && + tpmGuid.value.startsWith('01-') && + regGuid.value !== tpmGuid.value + ) +); const showTpmTransferButton = computed((): boolean => - Boolean((keyInstalled.value || showTrialExpiration.value) && hasDistinctTpmGuid.value) + Boolean( + hasDistinctTpmGuid.value && + (keyInstalled.value || showTrialExpiration.value || hasBlacklistedTpmLicenseMismatch.value) + ) ); const disableTpmTransferButton = computed((): boolean => showTrialExpiration.value); @@ -369,7 +383,7 @@ const actionItems = computed((): RegistrationItemProps[] => {

{{ t('registration.actions') }}

From 62cc29a16d2a609ba69e724015660911fc756491 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 10:12:43 +0100 Subject: [PATCH 03/16] chore(ai-review): record final review receipt --- ...-1117-tpm-blacklisted-pr-66d786804bbd.json | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index fe0124bdab..022992e791 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,30 +1,8 @@ { "disposition": "PATCH", - "expected_structural_delta": "Add no production modules, owners, dependencies, representations, or pass-through hops. Extend one existing Registration predicate, the existing PHP state fallback, and the existing Registration test file with focused positive and negative cases.", - "minimum_design": "Extend the existing Registration eligibility predicate to require normal EBLACKLISTED state, a key file, a flash boot device, a usable TPM GUID, and a different registered TPM GUID. Reuse the existing PHP state payload fallback and Account replacement operation.", - "outcome": "When the current boot device is a blacklisted flash, a usable new TPM is detected, and the installed key is registered to a different old TPM GUID, Registration shows the existing TPM key-replacement action.", - "reuse_decisions": [ - { - "decision": "extend", - "name": "Existing Registration TPM replacement action", - "rationale": "The component already owns the TPM eligibility predicate, button, payload, and Account action. Extending it keeps one customer-facing action and one effect path." - }, - { - "decision": "extend", - "name": "Existing server state representation", - "rationale": "The existing server store already exposes the boot, registered, and TPM identifiers. The PHP fallback supplies the missing TPM identifier." - }, - { - "decision": "reuse", - "name": "Account TPM replacement operation", - "rationale": "The existing Account replaceTpm operation already handles the replacement request. No provider operation is added." - }, - { - "decision": "not applicable", - "name": "Other blacklisted states and Core UI", - "rationale": "The ticket concerns normal EBLACKLISTED with a blacklisted flash and an old-TPM/new-TPM mismatch. Other blacklisted state codes and the separate Core UI are outside this causal path." - } - ], + "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", + "reviewed_sha": "20bc0b337851d88e54506f1352b59dc24dd7c7f1", "schema": "limetech.ai-review-marker.v2", - "stage": "forecast" + "stage": "final", + "unresolved_proportionality_findings": [] } From 8c85d76ce38f78ce0fee0e3852fd58688069a1e4 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 11:55:19 +0100 Subject: [PATCH 04/16] fix(registration): show replacement actions for TPM mismatch --- web/__test__/components/Registration.test.ts | 10 +++++++-- .../components/Registration.standalone.vue | 12 +---------- web/src/store/server.ts | 21 +++++++++++++++++++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index 0a87a3b12f..fb130b4014 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -380,12 +380,18 @@ describe('Registration.standalone.vue', () => { expect(moveButton.exists()).toBe(true); expect(moveButton.attributes('disabled')).toBeUndefined(); - expect(wrapper.text()).toContain('Blacklisted boot device GUID'); - expect(wrapper.find('[data-testid="key-actions"]').exists()).toBe(false); + expect(wrapper.text()).toContain('Registration key / boot device GUID mismatch'); + expect(wrapper.text()).not.toContain('Blacklisted boot device GUID'); + expect(wrapper.find('[data-testid="key-actions"]').exists()).toBe(true); + expect(serverStore.keyActions?.some((action) => action.name === 'replace')).toBe(true); await moveButton.trigger('click'); expect(accountStore.replaceTpm).toHaveBeenCalled(); + + serverStore.keyActions?.find((action) => action.name === 'replace')?.click?.(); + + expect(accountStore.replace).toHaveBeenCalled(); }); it('does not show Move License to TPM for invalid blacklisted states', async () => { diff --git a/web/src/components/Registration.standalone.vue b/web/src/components/Registration.standalone.vue index 6e35265c2c..17832fe804 100644 --- a/web/src/components/Registration.standalone.vue +++ b/web/src/components/Registration.standalone.vue @@ -49,9 +49,9 @@ const { flashProduct, flashVendor, guid, - keyfile, keyActions, computedRegDevs, + hasBlacklistedTpmLicenseMismatch, regGuid, regTm, regTo, @@ -129,16 +129,6 @@ const showPartnerActivationCode = computed(() => { (currentState === 'ENOKEYFILE' || currentState === 'TRIAL' || currentState === 'EEXPIRED') ); }); -const hasBlacklistedTpmLicenseMismatch = computed( - (): boolean => - state.value === 'EBLACKLISTED' && - Boolean( - keyfile.value && - regGuid.value.startsWith('01-') && - tpmGuid.value.startsWith('01-') && - regGuid.value !== tpmGuid.value - ) -); const showTpmTransferButton = computed((): boolean => Boolean( hasDistinctTpmGuid.value && diff --git a/web/src/store/server.ts b/web/src/store/server.ts index 5bde8e4b53..9bb2fe1807 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -145,6 +145,17 @@ export const useServerStore = defineStore('server', () => { } return guid.value || undefined; }); + const hasBlacklistedTpmLicenseMismatch = computed( + (): boolean => + state.value === 'EBLACKLISTED' && + Boolean( + keyfile.value && + hasDistinctTpmGuid.value && + regGuid.value.startsWith('01-') && + tpmGuid.value.startsWith('01-') && + regGuid.value !== tpmGuid.value + ) + ); const site = ref(''); const ssoEnabled = ref(false); const state = ref(); @@ -718,6 +729,15 @@ export const useServerStore = defineStore('server', () => { message: t('server.state.enoflash.message'), }; case 'EBLACKLISTED': + if (hasBlacklistedTpmLicenseMismatch.value) { + return { + actions: [replaceAction.value], + error: true, + humanReadable: t('server.state.eguid.humanReadable'), + heading: t('server.state.eguid.heading'), + message: t('server.state.eguid.messageMismatch'), + }; + } return { error: true, humanReadable: t('server.state.eblacklisted.humanReadable'), @@ -1436,6 +1456,7 @@ export const useServerStore = defineStore('server', () => { guid, bootDeviceType, hasDistinctTpmGuid, + hasBlacklistedTpmLicenseMismatch, bootedFromFlashWithInternalBootSetup, keyfile, inIframe, From 8ae5ac960737bd7612fef97e787739747852a525 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:04:44 +0100 Subject: [PATCH 05/16] fix(registration): clarify TPM mismatch replacement flow --- web/__test__/components/Registration.test.ts | 10 +++++++++- web/src/components/Registration.standalone.vue | 2 +- web/src/locales/en.json | 3 +++ web/src/store/server.ts | 6 +++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index fb130b4014..8a7b777661 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -380,10 +380,18 @@ describe('Registration.standalone.vue', () => { expect(moveButton.exists()).toBe(true); expect(moveButton.attributes('disabled')).toBeUndefined(); - expect(wrapper.text()).toContain('Registration key / boot device GUID mismatch'); + expect(wrapper.text()).toContain('License / TPM mismatch'); expect(wrapper.text()).not.toContain('Blacklisted boot device GUID'); + expect(wrapper.text()).not.toContain('copy the correct key file'); + expect(wrapper.text()).toContain('Your license is registered to a different TPM'); + expect(findItemByLabel(t('registration.registeredGuid'))?.props('text')).toBe( + '01-OLD-TPM-GUID-1234567890' + ); expect(wrapper.find('[data-testid="key-actions"]').exists()).toBe(true); expect(serverStore.keyActions?.some((action) => action.name === 'replace')).toBe(true); + expect(serverStore.keyActions?.find((action) => action.name === 'replace')?.text).toBe( + 'Replace Key' + ); await moveButton.trigger('click'); diff --git a/web/src/components/Registration.standalone.vue b/web/src/components/Registration.standalone.vue index 17832fe804..77272aa1c6 100644 --- a/web/src/components/Registration.standalone.vue +++ b/web/src/components/Registration.standalone.vue @@ -180,7 +180,7 @@ const bootDeviceItems = computed((): RegistrationItemProps[] => { }, ] : []), - ...(state.value === 'EGUID' + ...(state.value === 'EGUID' || hasBlacklistedTpmLicenseMismatch.value ? [ { label: t('registration.registeredGuid'), diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 0214592618..892c67aef1 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Blacklisted boot device GUID", "server.state.eblacklisted.humanReadable": "BLACKLISTED", "server.state.eblacklisted.message": "

This boot device has been blacklisted. This can occur as a result of transferring your license key to a replacement device, and you are currently booted from your old device.

A device may also be blacklisted if we discover the serial number is not unique – this is common with USB card readers.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Move License to TPM to replace the license on this TPM, or choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Boot device error", "server.state.eblacklisted1.message": "

This boot device has an invalid GUID. Please try a different boot device

", "server.state.eblacklisted2.heading": "Boot device has no serial number", diff --git a/web/src/store/server.ts b/web/src/store/server.ts index 9bb2fe1807..90ed60bf5f 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -733,9 +733,9 @@ export const useServerStore = defineStore('server', () => { return { actions: [replaceAction.value], error: true, - humanReadable: t('server.state.eguid.humanReadable'), - heading: t('server.state.eguid.heading'), - message: t('server.state.eguid.messageMismatch'), + humanReadable: t('server.state.eblacklisted.tpmMismatch.humanReadable'), + heading: t('server.state.eblacklisted.tpmMismatch.heading'), + message: t('server.state.eblacklisted.tpmMismatch.message'), }; } return { From 1fc0909580783cd5887d8f994f85b3b7baceda47 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:09:43 +0100 Subject: [PATCH 06/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index 022992e791..c690735bce 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "20bc0b337851d88e54506f1352b59dc24dd7c7f1", + "reviewed_sha": "8ae5ac960737bd7612fef97e787739747852a525", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": [] From ca7795552495a8da91ec8969028d216992c83310 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 13:24:27 +0100 Subject: [PATCH 07/16] fix(registration): hide redundant TPM transfer action --- web/__test__/components/Registration.test.ts | 14 +++++--------- web/src/components/Registration.standalone.vue | 10 +++++----- web/src/locales/en.json | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index 8a7b777661..e2111aa32e 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -366,7 +366,7 @@ describe('Registration.standalone.vue', () => { expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(true); }); - it('shows Move License to TPM when the boot flash is blacklisted but TPM licensing is available', async () => { + it('shows the TPM mismatch and Replace Key action when the boot flash is blacklisted', async () => { serverStore.state = 'EBLACKLISTED'; serverStore.guid = '058F-6387-0000-0000F1F1E1C6'; serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6'; @@ -376,14 +376,13 @@ describe('Registration.standalone.vue', () => { await wrapper.vm.$nextTick(); - const moveButton = wrapper.find('[data-testid="move-license-to-tpm"]'); - - expect(moveButton.exists()).toBe(true); - expect(moveButton.attributes('disabled')).toBeUndefined(); + expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false); expect(wrapper.text()).toContain('License / TPM mismatch'); expect(wrapper.text()).not.toContain('Blacklisted boot device GUID'); expect(wrapper.text()).not.toContain('copy the correct key file'); + expect(wrapper.text()).not.toContain('Move License to TPM'); expect(wrapper.text()).toContain('Your license is registered to a different TPM'); + expect(findItemByLabel(t('TPM GUID'))?.props('text')).toBe('01-V35H8S0L1QHK1SBG1XHXJNH7'); expect(findItemByLabel(t('registration.registeredGuid'))?.props('text')).toBe( '01-OLD-TPM-GUID-1234567890' ); @@ -393,13 +392,10 @@ describe('Registration.standalone.vue', () => { 'Replace Key' ); - await moveButton.trigger('click'); - - expect(accountStore.replaceTpm).toHaveBeenCalled(); - serverStore.keyActions?.find((action) => action.name === 'replace')?.click?.(); expect(accountStore.replace).toHaveBeenCalled(); + expect(accountStore.replaceTpm).not.toHaveBeenCalled(); }); it('does not show Move License to TPM for invalid blacklisted states', async () => { diff --git a/web/src/components/Registration.standalone.vue b/web/src/components/Registration.standalone.vue index 77272aa1c6..dc4fbb72bd 100644 --- a/web/src/components/Registration.standalone.vue +++ b/web/src/components/Registration.standalone.vue @@ -130,12 +130,12 @@ const showPartnerActivationCode = computed(() => { ); }); const showTpmTransferButton = computed((): boolean => - Boolean( - hasDistinctTpmGuid.value && - (keyInstalled.value || showTrialExpiration.value || hasBlacklistedTpmLicenseMismatch.value) - ) + Boolean(hasDistinctTpmGuid.value && (keyInstalled.value || showTrialExpiration.value)) ); const disableTpmTransferButton = computed((): boolean => showTrialExpiration.value); +const showTpmGuid = computed((): boolean => + Boolean(showTpmTransferButton.value || hasBlacklistedTpmLicenseMismatch.value) +); // Organize items into three sections const bootDeviceItems = computed((): RegistrationItemProps[] => { @@ -148,7 +148,7 @@ const bootDeviceItems = computed((): RegistrationItemProps[] => { }, ] : []), - ...(showTpmTransferButton.value && tpmGuid.value + ...(showTpmGuid.value && tpmGuid.value ? [ { label: t('registration.tpmGuid'), diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 892c67aef1..c968ea6f36 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -769,7 +769,7 @@ "server.state.eblacklisted.message": "

This boot device has been blacklisted. This can occur as a result of transferring your license key to a replacement device, and you are currently booted from your old device.

A device may also be blacklisted if we discover the serial number is not unique – this is common with USB card readers.

", "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", - "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Move License to TPM to replace the license on this TPM, or choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Boot device error", "server.state.eblacklisted1.message": "

This boot device has an invalid GUID. Please try a different boot device

", "server.state.eblacklisted2.heading": "Boot device has no serial number", From 0a3209ffde7233d0ffd12bd7cbd32d26ccc35304 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 13:27:06 +0100 Subject: [PATCH 08/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index c690735bce..bcd038ad07 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "8ae5ac960737bd7612fef97e787739747852a525", + "reviewed_sha": "ca7795552495a8da91ec8969028d216992c83310", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": [] From 6dd25d48f4807c235bc79a58c526901b96949301 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 13:42:55 +0100 Subject: [PATCH 09/16] fix(i18n): keep TPM mismatch keys in sync --- web/src/locales/ar.json | 3 +++ web/src/locales/bn.json | 3 +++ web/src/locales/ca.json | 3 +++ web/src/locales/cs.json | 3 +++ web/src/locales/da.json | 3 +++ web/src/locales/de.json | 3 +++ web/src/locales/es.json | 3 +++ web/src/locales/fr.json | 3 +++ web/src/locales/hi.json | 3 +++ web/src/locales/hr.json | 3 +++ web/src/locales/hu.json | 3 +++ web/src/locales/it.json | 3 +++ web/src/locales/ja.json | 3 +++ web/src/locales/ko.json | 3 +++ web/src/locales/lv.json | 3 +++ web/src/locales/nl.json | 3 +++ web/src/locales/no.json | 3 +++ web/src/locales/pl.json | 3 +++ web/src/locales/pt.json | 3 +++ web/src/locales/ro.json | 3 +++ web/src/locales/ru.json | 3 +++ web/src/locales/sv.json | 3 +++ web/src/locales/uk.json | 3 +++ web/src/locales/zh.json | 3 +++ 24 files changed, 72 insertions(+) diff --git a/web/src/locales/ar.json b/web/src/locales/ar.json index 87a358e882..37e0b05f4d 100644 --- a/web/src/locales/ar.json +++ b/web/src/locales/ar.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "معرّف الإقلاع المدرج بالقائمة السوداء", "server.state.eblacklisted.humanReadable": "مدرج بالقائمة السوداء", "server.state.eblacklisted.message": "

تم إدراج جهاز الإقلاع هذا على القائمة السوداء. يمكن أن يحدث هذا نتيجة نقل مفتاح الترخيص الخاص بك إلى جهاز بديل، وأنت تقوم حالياً بالإقلاع من جهازك القديم.

قد يكون الجهاز مدرجاً أيضاً بالقائمة السوداء إذا اكتشفنا أن الرقم التسلسلي غير فريد - وهذا شائع مع قارئات البطاقات USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "خطأ في جهاز الإقلاع", "server.state.eblacklisted1.message": "

جهاز الإقلاع هذا لديه معرّف غير صالح. الرجاء محاولة جهاز إقلاع مختلف

", "server.state.eblacklisted2.heading": "جهاز الإقلاع لا يحتوي على رقم تسلسلي", diff --git a/web/src/locales/bn.json b/web/src/locales/bn.json index 392d6a7f91..e40084cc17 100644 --- a/web/src/locales/bn.json +++ b/web/src/locales/bn.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "ব্ল্যাকলিস্টেড বুট ডিভাইস গাইড", "server.state.eblacklisted.humanReadable": "ব্ল্যাকলিস্টেড", "server.state.eblacklisted.message": "

এই বুট ডিভাইসটি ব্ল্যাকলিস্ট করা হয়েছে। এটি আপনার লাইসেন্স কী একটি প্রতিস্থাপন ডিভাইসে ট্রান্সফার করার ফলস্বরূপ হতে পারে, এবং আপাতত আপনি আপনার পুরনো ডিভাইস থেকে উঠেছেন।

ডিভাইসটিও ব্ল্যাকলিস্ট হতে পারে যদি আমরা অনন্য সিরিয়াল নম্বর না পাই – এটির মধ্যে ইউএসবি কার্ড রিডারে সাধারণ থাকে।

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "বুট ডিভাইস ত্রুটি", "server.state.eblacklisted1.message": "

এই বুট ডিভাইসে অবৈধ গাইড হয়েছে। অনুগ্রহ করে অন্য এক বুট ডিভাইস চেষ্টা করুন।

", "server.state.eblacklisted2.heading": "বুট ডিভাইসে কোনো সিরিয়াল নম্বর নেই", diff --git a/web/src/locales/ca.json b/web/src/locales/ca.json index 938f089c85..cb7980b948 100644 --- a/web/src/locales/ca.json +++ b/web/src/locales/ca.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Dispositiu de arrencada en llista negra GUID", "server.state.eblacklisted.humanReadable": "EN LLISTA NEGRA", "server.state.eblacklisted.message": "

Aquest dispositiu d'arrencada ha estat posat a la llista negra. Això pot passar com a resultat de transferir la vostra clau de llicència a un dispositiu de reemplaçament, i actualment esteu arrencant des del vostre dispositiu antic.

Un dispositiu també es pot incloure en la llista negra si descobrim que el número de sèrie no és únic – això és comú amb els lectors de targetes USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Error de dispositiu d'arrencada", "server.state.eblacklisted1.message": "

Aquest dispositiu d'arrencada té un GUID no vàlid. Si us plau, proveu amb un altre dispositiu d'arrencada

", "server.state.eblacklisted2.heading": "El dispositiu d'arrencada no té número de sèrie", diff --git a/web/src/locales/cs.json b/web/src/locales/cs.json index 2726d5205c..5ac23cd2ec 100644 --- a/web/src/locales/cs.json +++ b/web/src/locales/cs.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Zakázaný GUID boot zařízení", "server.state.eblacklisted.humanReadable": "ČERNÁ LISTINA", "server.state.eblacklisted.message": "

Toto boot zařízení bylo zakázáno. To může nastat v důsledku převodu vašeho licenčního klíče na náhradní zařízení a aktuálně bootujete ze starého zařízení.

Zařízení může být také zakázáno, pokud zjistíme, že sériové číslo není unikátní — to je běžné u USB čteček karet.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Chyba boot zařízení", "server.state.eblacklisted1.message": "

Toto boot zařízení má neplatný GUID. Zkuste prosím jiné boot zařízení

", "server.state.eblacklisted2.heading": "Boot zařízení nemá sériové číslo", diff --git a/web/src/locales/da.json b/web/src/locales/da.json index b602d7bf2c..13bde79f13 100644 --- a/web/src/locales/da.json +++ b/web/src/locales/da.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Blacklistet boot-enhed GUID", "server.state.eblacklisted.humanReadable": "BLACKLISTED", "server.state.eblacklisted.message": "

Denne boot-enhed er blevet blacklistet. Dette kan ske som følge af at overføre din licensnøgle til en erstatningsenhed, og du er i øjeblikket startet fra din gamle enhed.

En enhed kan også blive blacklistet, hvis vi opdager, at serienummeret ikke er unikt – dette er almindeligt med USB-kortlæsere.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Boot-enhed fejl", "server.state.eblacklisted1.message": "

Denne boot-enhed har en ugyldig GUID. Prøv venligst en anden boot-enhed

", "server.state.eblacklisted2.heading": "Boot-enhed har ikke noget serienummer", diff --git a/web/src/locales/de.json b/web/src/locales/de.json index 7764e4f823..a3f34128a6 100644 --- a/web/src/locales/de.json +++ b/web/src/locales/de.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Schwarze Liste Boot-Gerät-GUID", "server.state.eblacklisted.humanReadable": "AUF DER SCHWARZEN LISTE", "server.state.eblacklisted.message": "

Dieses Boot-Gerät wurde auf die schwarze Liste gesetzt. Dies kann passieren, wenn Ihr Lizenzschlüssel auf ein Ersatzgerät übertragen wurde und das Gerät, von dem Sie starten, das alte Gerät ist.

Ein Gerät kann auch auf die schwarze Liste gesetzt werden, wenn wir feststellen, dass die Seriennummer nicht eindeutig ist – was bei USB-Kartenlesern häufig vorkommt.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Boot-Gerätefehler", "server.state.eblacklisted1.message": "

Dieses Boot-Gerät hat eine ungültige GUID. Bitte versuchen Sie ein anderes Boot-Gerät

", "server.state.eblacklisted2.heading": "Boot-Gerät hat keine Seriennummer", diff --git a/web/src/locales/es.json b/web/src/locales/es.json index 9752c1b0ab..fd6fe38e71 100644 --- a/web/src/locales/es.json +++ b/web/src/locales/es.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Dispositivo de arranque en la lista negra GUID", "server.state.eblacklisted.humanReadable": "EN LISTA NEGRA", "server.state.eblacklisted.message": "

Este dispositivo de arranque ha sido incluido en la lista negra. Esto puede ocurrir como resultado de transferir su clave de licencia a un dispositivo de reemplazo, y actualmente está arrancando desde su dispositivo antiguo.

Un dispositivo también puede ser incluido en la lista negra si descubrimos que el número de serie no es único, lo cual es común con lectores de tarjetas USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Error del dispositivo de arranque", "server.state.eblacklisted1.message": "

Este dispositivo de arranque tiene un GUID inválido. Por favor, pruebe con un dispositivo de arranque diferente.

", "server.state.eblacklisted2.heading": "El dispositivo de arranque no tiene número de serie", diff --git a/web/src/locales/fr.json b/web/src/locales/fr.json index 2bd3c10cde..fec432e751 100644 --- a/web/src/locales/fr.json +++ b/web/src/locales/fr.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "GUID de l'appareil de démarrage sur liste noire", "server.state.eblacklisted.humanReadable": "SUR LISTE NOIRE", "server.state.eblacklisted.message": "

Cet appareil de démarrage a été mis sur liste noire. Cela peut se produire à la suite du transfert de votre clé de licence vers un appareil de remplacement, et vous êtes actuellement démarré à partir de votre ancien appareil.

Un appareil peut également être mis sur liste noire si nous découvrons que le numéro de série n'est pas unique, ce qui est courant avec les lecteurs de carte USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Erreur de l'appareil de démarrage", "server.state.eblacklisted1.message": "

Cet appareil de démarrage a un GUID invalide. Veuillez essayer un autre appareil de démarrage.

", "server.state.eblacklisted2.heading": "L'appareil de démarrage n'a pas de numéro de série", diff --git a/web/src/locales/hi.json b/web/src/locales/hi.json index 41d1b148f3..c0a520d41b 100644 --- a/web/src/locales/hi.json +++ b/web/src/locales/hi.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "ब्लैकलिस्टेड बूट उपकरण GUID", "server.state.eblacklisted.humanReadable": "ब्लैकलिस्टेड", "server.state.eblacklisted.message": "

यह बूट उपकरण ब्लैकलिस्टेड है। यह आपके लाइसेंस कुंजी को प्रतिस्थापन उपकरण में स्थानांतरित करने के कारण हो सकता है, और आप वर्तमान में अपने पुराने उपकरण से बूट किए गए हैं।

यदि हम पाते हैं कि सीरियल नंबर अद्वितीय नहीं है - यह यूएसबी कार्ड पाठकों के साथ सामान्य है, तो भी एक उपकरण को ब्लैकलिस्टेड किया जा सकता है।

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "बूट उपकरण त्रुटि", "server.state.eblacklisted1.message": "

इस बूट उपकरण का GUID अमान्य है। कृपया एक अलग बूट उपकरण आजमाएं।

", "server.state.eblacklisted2.heading": "बूट उपकरण का कोई सीरियल नंबर नहीं है", diff --git a/web/src/locales/hr.json b/web/src/locales/hr.json index 92e78362b8..e87522d720 100644 --- a/web/src/locales/hr.json +++ b/web/src/locales/hr.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Na crnoj listi podizanja sustava GUID uređaja", "server.state.eblacklisted.humanReadable": "CRNA LISTA", "server.state.eblacklisted.message": "

Ovaj uređaj za podizanje sustava je na crnoj listi. To se može dogoditi kao rezultat prijenosa vašeg licencnog ključa na zamjenski uređaj, a trenutno ste podigli sustav s vašeg starog uređaja.

Uređaj može također biti na crnoj listi ako otkrijemo da serijski broj nije jedinstven – što je uobičajeno s USB čitačima kartica.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Greška uređaja za podizanje sustava", "server.state.eblacklisted1.message": "

Ovaj uređaj za podizanje sustava ima nevažeći GUID. Molimo pokušajte s drugim uređajem za podizanje sustava

", "server.state.eblacklisted2.heading": "Uređaj za podizanje sustava nema serijski broj", diff --git a/web/src/locales/hu.json b/web/src/locales/hu.json index 65081def15..274236ea8d 100644 --- a/web/src/locales/hu.json +++ b/web/src/locales/hu.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Rendszerindító eszköz GUID-je letiltva", "server.state.eblacklisted.humanReadable": "LETILTVA", "server.state.eblacklisted.message": "

Ez a rendszerindító eszköz tiltólistára került. Ez akkor fordulhat elő, ha a licenckulcsát egy csereeszközre helyezte át, és jelenleg a régi eszközről indította a rendszert.

Egy eszköz akkor is tiltólistára kerülhet, ha úgy találjuk, hogy a sorozatszáma nem egyedi – ez gyakori az USB-s kártyaolvasóknál.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Hiba a rendszerindító eszközön", "server.state.eblacklisted1.message": "

Érvénytelen a rendszerindító eszköz GUID-je. Kérjük, próbálkozzon egy másik rendszerindító eszközzel.

", "server.state.eblacklisted2.heading": "Nincs sorozatszáma a rendszerindító eszköznek", diff --git a/web/src/locales/it.json b/web/src/locales/it.json index 7815ef4042..e427bbda34 100644 --- a/web/src/locales/it.json +++ b/web/src/locales/it.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "GUID dispositivo di avvio nella lista nera", "server.state.eblacklisted.humanReadable": "LISTA NERA", "server.state.eblacklisted.message": "

Questo dispositivo di avvio è stato inserito nella lista nera. Questo può accadere a seguito del trasferimento della tua chiave di licenza a un dispositivo di sostituzione, e attualmente sei avviato dal tuo vecchio dispositivo.

Un dispositivo può anche essere inserito nella lista nera se scopriamo che il numero di serie non è unico; questo è comune con i lettori di schede USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Errore dispositivo di avvio", "server.state.eblacklisted1.message": "

Questo dispositivo di avvio ha un GUID non valido. Si prega di provare un dispositivo di avvio diverso

", "server.state.eblacklisted2.heading": "Il dispositivo di avvio non ha numero di serie", diff --git a/web/src/locales/ja.json b/web/src/locales/ja.json index 165d0ab231..a0f8374ed4 100644 --- a/web/src/locales/ja.json +++ b/web/src/locales/ja.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "ブラックリストに登録されたブートデバイスGUID", "server.state.eblacklisted.humanReadable": "ブラックリスト", "server.state.eblacklisted.message": "

このブートデバイスはブラックリストに登録されています。これはライセンスキーを交換デバイスに転送した結果が原因であり、現在古いデバイスからブートされています。

また、シリアル番号が一意でないと判明した場合、デバイスはブラックリストに登録される可能性があります。これはUSBカードリーダーでよくあります。

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "ブートデバイスエラー", "server.state.eblacklisted1.message": "

このブートデバイスは無効なGUIDを持っています。別のブートデバイスを試してください。

", "server.state.eblacklisted2.heading": "ブートデバイスにシリアル番号がありません", diff --git a/web/src/locales/ko.json b/web/src/locales/ko.json index 4df0b33483..54c212ddac 100644 --- a/web/src/locales/ko.json +++ b/web/src/locales/ko.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "블랙리스트에 등록된 부팅 디바이스 GUID", "server.state.eblacklisted.humanReadable": "블랙리스트됨", "server.state.eblacklisted.message": "

이 부팅 디바이스는 블랙리스트에 등록되었습니다. 이는 라이센스 키를 대체 디바이스로 이전한 결과로 발생할 수 있으며, 현재 이전 사용 중인 디바이스에서 부팅 중입니다.

디바이스 일련번호가 유일하지 않음을 발견하면 디바이스가 블랙리스트에 등록될 수 있습니다. 이는 USB 카드 리더기에서 일반적입니다.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "부팅 디바이스 오류", "server.state.eblacklisted1.message": "

이 부팅 디바이스의 GUID가 유효하지 않습니다. 다른 부팅 디바이스를 시도하세요.

", "server.state.eblacklisted2.heading": "부팅 디바이스에 일련번호가 없습니다.", diff --git a/web/src/locales/lv.json b/web/src/locales/lv.json index ab73b95bea..dbfd45013d 100644 --- a/web/src/locales/lv.json +++ b/web/src/locales/lv.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Melnajā sarakstā iekļautais palaišanas ierīces GUID", "server.state.eblacklisted.humanReadable": "MELNĀ SARAKSTA", "server.state.eblacklisted.message": "

Šī palaišanas ierīce ir iekļauta melnajā sarakstā. Tas var notikt licences atslēgas pārneses uz aizstājēju ierīci rezultātā, un pašlaik jūs tiekat palaists no vecās ierīces.

Ierīce var tikt melnajā sarakstā iekļauta arī, ja atklājam, ka sērijas numurs nav unikāls – tas ir raksturīgi USB kartes lasītājiem.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Palaišanas ierīces kļūda", "server.state.eblacklisted1.message": "

Šai palaišanas ierīcei ir nederīgs GUID. Lūdzu, izmēģiniet citu palaišanas ierīci

", "server.state.eblacklisted2.heading": "Palaišanas ierīcei nav sērijas numura", diff --git a/web/src/locales/nl.json b/web/src/locales/nl.json index 3271dcdd03..efe7000e99 100644 --- a/web/src/locales/nl.json +++ b/web/src/locales/nl.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Opstartapparaat op zwarte lijst GUID", "server.state.eblacklisted.humanReadable": "Zwarte Lijst", "server.state.eblacklisted.message": "

Dit opstartapparaat is op de zwarte lijst gezet. Dit kan een gevolg zijn van het overzetten van uw licentiesleutel naar een vervangend apparaat, en u bent momenteel opgestart vanaf uw oude apparaat.

Een apparaat kan ook op de zwarte lijst worden gezet als we ontdekken dat het serienummer niet uniek is – dit gebeurt vaak bij USB-kaartlezers.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Opstartapparaatfout", "server.state.eblacklisted1.message": "

Dit opstartapparaat heeft een ongeldige GUID. Probeer een ander opstartapparaat

", "server.state.eblacklisted2.heading": "Opstartapparaat heeft geen serienummer", diff --git a/web/src/locales/no.json b/web/src/locales/no.json index 5813d02500..6ccd40b790 100644 --- a/web/src/locales/no.json +++ b/web/src/locales/no.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Svartelistet oppstartsenhet GUID", "server.state.eblacklisted.humanReadable": "SVARTE LISTET", "server.state.eblacklisted.message": "

Denne oppstartsenheten er svartelistet. Dette kan skje som et resultat av å overføre lisensnøkkelen din til en erstatningsenhet, og du er for øyeblikket startet fra den gamle enheten din.

En enhet kan også bli svartelistet hvis vi oppdager at serienummeret ikke er unikt – dette er vanlig med USB-kortlesere.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Startenhetsfeil", "server.state.eblacklisted1.message": "

Denne oppstartsenheten har en ugyldig GUID. Prøv en annen oppstartsenhet

", "server.state.eblacklisted2.heading": "Oppstartsenheten har ikke noe serienummer", diff --git a/web/src/locales/pl.json b/web/src/locales/pl.json index 9648d9a2b0..28f1b09ddc 100644 --- a/web/src/locales/pl.json +++ b/web/src/locales/pl.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Czarna lista GUID urządzenia rozruchowego", "server.state.eblacklisted.humanReadable": "CZARNA LISTA", "server.state.eblacklisted.message": "

To urządzenie rozruchowe zostało umieszczone na czarnej liście. Może się to zdarzyć w wyniku przeniesienia klucza licencyjnego na urządzenie zastępcze, a aktualnie uruchamiane jest z rozruchu starego urządzenia.

Urządzenie może również trafić na czarną listę, jeśli odkryjemy, że numer seryjny nie jest unikalny – co jest często spotykane w przypadku czytników kart USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Błąd urządzenia rozruchowego", "server.state.eblacklisted1.message": "

To urządzenie rozruchowe ma nieprawidłowy identyfikator GUID. Proszę spróbować użycia innego urządzenia rozruchowego

", "server.state.eblacklisted2.heading": "Urządzenie rozruchowe nie ma numeru seryjnego", diff --git a/web/src/locales/pt.json b/web/src/locales/pt.json index bee9f83a9b..da7e6b766b 100644 --- a/web/src/locales/pt.json +++ b/web/src/locales/pt.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "GUID do dispositivo de boot na lista negra", "server.state.eblacklisted.humanReadable": "NA LISTA NEGRA", "server.state.eblacklisted.message": "

Este dispositivo de boot está na lista negra. Isso pode ocorrer como resultado de uma transferência da chave de licença para um dispositivo de substituição, e você está inicializado atualmente do dispositivo antigo.

Um dispositivo também pode ser adicionado à lista negra se descobrirmos que o número de série não é único – isso é comum com leitores de cartões USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Erro no dispositivo de boot", "server.state.eblacklisted1.message": "

Este dispositivo de boot possui um GUID inválido. Por favor, tente um dispositivo de boot diferente

", "server.state.eblacklisted2.heading": "Dispositivo de boot sem número de série", diff --git a/web/src/locales/ro.json b/web/src/locales/ro.json index 1ccdc8c858..be0533d923 100644 --- a/web/src/locales/ro.json +++ b/web/src/locales/ro.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "GUID dispozitiv boot pe lista neagră", "server.state.eblacklisted.humanReadable": "LISTĂ NEAGRĂ", "server.state.eblacklisted.message": "

Acest dispozitiv de boot este pe lista neagră. Acest lucru poate apărea ca rezultat al transferului cheii de licență către un dispozitiv de înlocuire și sunteți în prezent inițiat de pe dispozitivul vechi.

Un dispozitiv poate fi, de asemenea, pus pe lista neagră dacă descoperim că numărul de serie nu este unic – acest lucru este comun cu cititoarele de carduri USB.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Eroare dispozitiv boot", "server.state.eblacklisted1.message": "

Acest dispozitiv de boot are un GUID invalid. Vă rugăm să încercați un alt dispozitiv de boot.

", "server.state.eblacklisted2.heading": "Dispozitivul de boot nu are număr de serie", diff --git a/web/src/locales/ru.json b/web/src/locales/ru.json index 9e69cda4d6..61a4180959 100644 --- a/web/src/locales/ru.json +++ b/web/src/locales/ru.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "GUID устройства загрузки в черном списке", "server.state.eblacklisted.humanReadable": "ЧЕРНЫЙ СПИСОК", "server.state.eblacklisted.message": "

Это загрузочное устройство добавлено в черный список. Это может произойти в результате передачи вашего лицензионного ключа на замену устройства, и в настоящее время вы загружаетесь со старого устройства.

Устройство также может быть добавлено в черный список, если мы обнаружим, что серийный номер не уникален – это часто случается с USB кард-ридерами.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Ошибка загрузочного устройства", "server.state.eblacklisted1.message": "

У этого загрузочного устройства недействительный GUID. Попробуйте использовать другое загрузочное устройство

", "server.state.eblacklisted2.heading": "У загрузочного устройства нет серийного номера", diff --git a/web/src/locales/sv.json b/web/src/locales/sv.json index fdf961a85a..3a7bc1e104 100644 --- a/web/src/locales/sv.json +++ b/web/src/locales/sv.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "Svartlistad bootenhets-GUID", "server.state.eblacklisted.humanReadable": "SVARTLISTAD", "server.state.eblacklisted.message": "

Denna bootenhet har blivit svartlistad. Detta kan ske till följd av att din licensnyckel har överförts till en ersättningsenhet, och du är för närvarande startad från din gamla enhet.

En enhet kan också bli svartlistad om vi upptäcker att serienumret inte är unikt – detta är vanligt med USB-kortläsare.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Boothenhetsfel", "server.state.eblacklisted1.message": "

Denna boothenhet har en ogiltig GUID. Försök med en annan boothenhet

", "server.state.eblacklisted2.heading": "Boothenheten har inget serienummer", diff --git a/web/src/locales/uk.json b/web/src/locales/uk.json index c41f8ec33f..fbb0884187 100644 --- a/web/src/locales/uk.json +++ b/web/src/locales/uk.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "В чорному списку GUID завантажувального пристрою", "server.state.eblacklisted.humanReadable": "ЧОРНИЙ СПИСОК", "server.state.eblacklisted.message": "

Цей завантажувальний пристрій внесено до чорного списку. Це може статися в результаті передачі вашого ліцензійного ключа на замінний пристрій, і ви наразі завантажилися зі старого пристрою.

Пристрій також може бути занесений до чорного списку, якщо ми виявимо, що серійний номер не є унікальним - це поширено для USB-картридерів.

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "Помилка завантажувального пристрою", "server.state.eblacklisted1.message": "

Цей завантажувальний пристрій має недійсний GUID. Будь ласка, спробуйте інший завантажувальний пристрій

", "server.state.eblacklisted2.heading": "Завантажувальний пристрій не має серійного номера", diff --git a/web/src/locales/zh.json b/web/src/locales/zh.json index 57bb60a8fa..ae927f2ddb 100644 --- a/web/src/locales/zh.json +++ b/web/src/locales/zh.json @@ -767,6 +767,9 @@ "server.state.eblacklisted.heading": "列入黑名单的引导设备 GUID", "server.state.eblacklisted.humanReadable": "列入黑名单", "server.state.eblacklisted.message": "

此引导设备已列入黑名单。这可能是由于将您的许可证密钥转移到更换设备,而您当前正在从旧设备启动。

如果我们发现序列号不是唯一的,设备也可能会被列入黑名单 —— 这在 USB 卡读取器中很常见。

", + "server.state.eblacklisted.tpmMismatch.heading": "License / TPM mismatch", + "server.state.eblacklisted.tpmMismatch.humanReadable": "LICENSE / TPM MISMATCH", + "server.state.eblacklisted.tpmMismatch.message": "

Your license is registered to a different TPM than the one currently detected. This can occur after a hardware swap.

Choose Replace Key to start the license replacement flow. The blacklisted boot flash will not be changed.

", "server.state.eblacklisted1.heading": "引导设备错误", "server.state.eblacklisted1.message": "

此引导设备的 GUID 无效。请尝试其他引导设备

", "server.state.eblacklisted2.heading": "引导设备没有序列号", From 5f216d894663f40f9174f299d9e98392c91b97fe Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 13:44:20 +0100 Subject: [PATCH 10/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index bcd038ad07..146f5b3a0b 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "ca7795552495a8da91ec8969028d216992c83310", + "reviewed_sha": "6dd25d48f4807c235bc79a58c526901b96949301", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": [] From b7aa4e3b7f5b76efaf2e05cc685cdda0b0f32471 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:52:18 +0100 Subject: [PATCH 11/16] fix(registration): replace TPM license using registered GUID For CLD-1117, pass the old registered TPM GUID to the Replace Key callback when a blacklisted flash boot device has a TPM-bound license mismatch. Keep the normal Move License to TPM payload pointed at the detected TPM. Linear: https://linear.app/lime-technology/issue/CLD-1117/registration-suppresses-tpm-replace-key-flow-when-boot-usb-is --- web/__test__/components/Registration.test.ts | 4 +++- web/__test__/store/account.test.ts | 25 ++++++++++++++++++++ web/src/store/account.ts | 4 ++-- web/src/store/server.ts | 6 ++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index e2111aa32e..398fca99d0 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -394,7 +394,9 @@ describe('Registration.standalone.vue', () => { serverStore.keyActions?.find((action) => action.name === 'replace')?.click?.(); - expect(accountStore.replace).toHaveBeenCalled(); + expect(accountStore.replace).toHaveBeenCalledWith( + expect.objectContaining({ guid: '01-OLD-TPM-GUID-1234567890' }) + ); expect(accountStore.replaceTpm).not.toHaveBeenCalled(); }); diff --git a/web/__test__/store/account.test.ts b/web/__test__/store/account.test.ts index 01a4d155f0..4e73b25d76 100644 --- a/web/__test__/store/account.test.ts +++ b/web/__test__/store/account.test.ts @@ -257,6 +257,31 @@ describe('Account Store', () => { ); }); + it('should forward a supplied server payload for replace', () => { + const replacementPayload = { + guid: '01-old-tpm-guid', + keyfile: 'test-keyfile', + name: 'test-server', + registered: true, + state: 'EBLACKLISTED' as const, + }; + + store.replace(replacementPayload); + + expect(mockSend).toHaveBeenCalledTimes(1); + expect(mockSend).toHaveBeenCalledWith( + ACCOUNT_CALLBACK.toString(), + [ + { + server: replacementPayload, + type: 'replace', + }, + ], + undefined, + 'post' + ); + }); + it('should forward the full server payload for replaceTpm', () => { store.replaceTpm(); diff --git a/web/src/store/account.ts b/web/src/store/account.ts index ca6ee2a198..21372eb1f6 100644 --- a/web/src/store/account.ts +++ b/web/src/store/account.ts @@ -183,8 +183,8 @@ export const useAccountStore = defineStore('account', () => { const recover = () => { sendAccountAction('recover'); }; - const replace = () => { - sendAccountAction('replace'); + const replace = (serverPayload?: ServerData) => { + sendAccountAction('replace', { serverPayload }); }; const replaceTpm = () => { sendAccountAction('replace', { serverPayload: serverReplacePayload.value }); diff --git a/web/src/store/server.ts b/web/src/store/server.ts index 90ed60bf5f..c1c50ccb40 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -444,7 +444,11 @@ export const useServerStore = defineStore('server', () => { const replaceAction = computed((): ServerStateDataAction => { return { click: () => { - accountStore.replace(); + accountStore.replace( + hasBlacklistedTpmLicenseMismatch.value + ? buildServerCallbackPayload({ guid: regGuid.value }) + : undefined + ); }, external: true, icon: KeyIcon, From 1f85d304e9c62ee777834047ce6c0dc201d6cc5e Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:53:44 +0100 Subject: [PATCH 12/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index 146f5b3a0b..83a5f7f57f 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "6dd25d48f4807c235bc79a58c526901b96949301", + "reviewed_sha": "b7aa4e3b7f5b76efaf2e05cc685cdda0b0f32471", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": [] From 64b94400b52f37024415ccf6450672b6c5dd1c7a Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:28:19 +0100 Subject: [PATCH 13/16] fix(registration): target detected TPM in key replacement --- web/__test__/components/Registration.test.ts | 5 ++++- web/src/store/server.ts | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index 398fca99d0..b87d92e694 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -395,7 +395,10 @@ describe('Registration.standalone.vue', () => { serverStore.keyActions?.find((action) => action.name === 'replace')?.click?.(); expect(accountStore.replace).toHaveBeenCalledWith( - expect.objectContaining({ guid: '01-OLD-TPM-GUID-1234567890' }) + expect.objectContaining({ + guid: '01-V35H8S0L1QHK1SBG1XHXJNH7', + regGuid: '01-OLD-TPM-GUID-1234567890', + }) ); expect(accountStore.replaceTpm).not.toHaveBeenCalled(); }); diff --git a/web/src/store/server.ts b/web/src/store/server.ts index c1c50ccb40..b70295fb79 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -445,9 +445,7 @@ export const useServerStore = defineStore('server', () => { return { click: () => { accountStore.replace( - hasBlacklistedTpmLicenseMismatch.value - ? buildServerCallbackPayload({ guid: regGuid.value }) - : undefined + hasBlacklistedTpmLicenseMismatch.value ? serverReplacePayload.value : undefined ); }, external: true, From 85e42dbe89ecc6696e72c6ffae4494781e30e033 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:28:30 +0100 Subject: [PATCH 14/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index 83a5f7f57f..ffe4a10b76 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "b7aa4e3b7f5b76efaf2e05cc685cdda0b0f32471", + "reviewed_sha": "64b94400b52f37024415ccf6450672b6c5dd1c7a", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": [] From 99f842b895eda84febe8448587f79b48ea2fda35 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:05:28 +0100 Subject: [PATCH 15/16] fix(registration): report TPM mismatch in replacement callback --- web/__test__/components/Registration.test.ts | 2 ++ web/src/store/server.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts index b87d92e694..af0254482a 100644 --- a/web/__test__/components/Registration.test.ts +++ b/web/__test__/components/Registration.test.ts @@ -398,8 +398,10 @@ describe('Registration.standalone.vue', () => { expect.objectContaining({ guid: '01-V35H8S0L1QHK1SBG1XHXJNH7', regGuid: '01-OLD-TPM-GUID-1234567890', + state: 'EGUID', }) ); + expect(serverStore.state).toBe('EBLACKLISTED'); expect(accountStore.replaceTpm).not.toHaveBeenCalled(); }); diff --git a/web/src/store/server.ts b/web/src/store/server.ts index b70295fb79..8406a311ee 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -445,7 +445,9 @@ export const useServerStore = defineStore('server', () => { return { click: () => { accountStore.replace( - hasBlacklistedTpmLicenseMismatch.value ? serverReplacePayload.value : undefined + hasBlacklistedTpmLicenseMismatch.value + ? { ...serverReplacePayload.value, state: 'EGUID' } + : undefined ); }, external: true, From aad603d6eb40e74bd86c92f80f45284d94c553fa Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:05:59 +0100 Subject: [PATCH 16/16] chore(ai-review): record final review receipt --- .../ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json index ffe4a10b76..0dcab9372d 100644 --- a/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json +++ b/.limetech/ai-review-markers/ai-cld-1117-tpm-blacklisted-pr-66d786804bbd.json @@ -1,7 +1,7 @@ { "disposition": "PATCH", "forecast_commit": "4ea919b834a792e0fef28d00895c16e7d64ca9a3", - "reviewed_sha": "64b94400b52f37024415ccf6450672b6c5dd1c7a", + "reviewed_sha": "99f842b895eda84febe8448587f79b48ea2fda35", "schema": "limetech.ai-review-marker.v2", "stage": "final", "unresolved_proportionality_findings": []