diff --git a/windows/welcome/src/SilverOS.Welcome.App/wwwroot/css/app.css b/windows/welcome/src/SilverOS.Welcome.App/wwwroot/css/app.css
index 555a055..13309f1 100644
--- a/windows/welcome/src/SilverOS.Welcome.App/wwwroot/css/app.css
+++ b/windows/welcome/src/SilverOS.Welcome.App/wwwroot/css/app.css
@@ -877,3 +877,27 @@ h1:focus { outline: none; }
padding-left: env(safe-area-inset-left);
}
}
+
+/* ── BitLocker recovery key (Done step) ─────────────────────────────── */
+.recovery-panel {
+ margin: 1.25rem 0;
+ padding: 1rem 1.25rem;
+ border: 1px solid var(--clr-accent);
+ border-radius: var(--radius-sm, 8px);
+ background: var(--clr-accent-glow, rgba(0,212,255,0.10));
+}
+.recovery-panel h3 { margin: 0 0 0.5rem; color: var(--clr-accent); font-family: var(--font-mono); }
+.recovery-key {
+ font-family: var(--font-mono);
+ font-size: 1.05rem;
+ letter-spacing: 0.04em;
+ color: var(--clr-text-hi);
+ background: rgba(0,0,0,0.30);
+ padding: 0.75rem 1rem;
+ border-radius: var(--radius-sm, 8px);
+ white-space: pre-wrap;
+ word-break: break-all;
+ user-select: all;
+ margin: 0.5rem 0;
+}
+.recovery-note { color: var(--clr-text-lo); }
diff --git a/windows/welcome/src/SilverOS.Welcome.Core/Apply/BitLockerService.cs b/windows/welcome/src/SilverOS.Welcome.Core/Apply/BitLockerService.cs
index fb6792c..f47dc8c 100644
--- a/windows/welcome/src/SilverOS.Welcome.Core/Apply/BitLockerService.cs
+++ b/windows/welcome/src/SilverOS.Welcome.Core/Apply/BitLockerService.cs
@@ -31,7 +31,12 @@ public sealed class BitLockerService(IProcessRunner runner) : IBitLockerService
"$p=ConvertTo-SecureString '", p, "' -AsPlainText -Force; ",
"$v=Get-BitLockerVolume -MountPoint $mp; ",
"if ($v.VolumeStatus -eq 'FullyDecrypted') { ",
- "Enable-BitLocker -MountPoint $mp -EncryptionMethod XtsAes256 -TpmAndPinProtector -Pin $p -SkipHardwareTest } ",
+ // NO -SkipHardwareTest: let BitLocker run its hardware test on the next reboot so it
+ // VALIDATES the TPM+PIN unseal against the real boot measurements before encrypting.
+ // -SkipHardwareTest seals immediately against possibly-wrong PCRs -> drops to recovery
+ // on first boot (E_FVE_SECURE_BOOT_CHANGED, PCR 11). The wizard's end-of-flow reboot
+ // is that validation pass, so the PIN works on first boot instead of bouncing.
+ "Enable-BitLocker -MountPoint $mp -EncryptionMethod XtsAes256 -TpmAndPinProtector -Pin $p } ",
"elseif (-not ($v.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'TpmPin' })) { ",
"Add-BitLockerKeyProtector -MountPoint $mp -TpmAndPinProtector -Pin $p }; ",
"$kp=(Get-BitLockerVolume -MountPoint $mp).KeyProtector; ",
diff --git a/windows/welcome/src/SilverOS.Welcome.UI/Components/Routes.razor b/windows/welcome/src/SilverOS.Welcome.UI/Components/Routes.razor
index 082ca0f..f4bb24c 100644
--- a/windows/welcome/src/SilverOS.Welcome.UI/Components/Routes.razor
+++ b/windows/welcome/src/SilverOS.Welcome.UI/Components/Routes.razor
@@ -37,7 +37,7 @@
Your SilverOS device is configured and ready. Click below to restart and start using it.
+Your SilverMetal device is configured and ready.
+ + @if (!string.IsNullOrWhiteSpace(_recoveryKey)) + { ++ This is the only way back into your drive if you ever forget your PIN. + Write it down or photograph it now and keep it somewhere safe and separate from this device. +
+@_recoveryKey+
Also saved to C:\ProgramData\SilverMetal\bitlocker-recovery.txt on this device.
Click below to restart and start using it.