diff --git a/windows/welcome-app-spec.md b/windows/welcome-app-spec.md index ab2be13..a5ffc7d 100644 --- a/windows/welcome-app-spec.md +++ b/windows/welcome-app-spec.md @@ -109,3 +109,19 @@ A flavour is a JSON file in `windows/flavours/` baked into the image: - **Kiosk lock-down of the bootstrap session** — ensure the user can't escape the wizard to a privileged shell before the real account exists. - **Apply failure handling** — if a module fails mid-apply, the wizard must surface it and leave the device in a recoverable state (don't delete bootstrap until apply + account creation succeed). - **Admin-credential UX** — confirm the daily/admin two-password step is clear (vs. generating + showing the admin secret once); ensure password strength rules on both. + +## 10. VM end-to-end validation — VALIDATED 2026-06-09 + +Built the packed ISO via CI (`build-iso-windows.yaml`, all green: 22 unit/bUnit tests + ISO bake + offline payload assertions) and ran it on SLAB01 VM 102 (UEFI + SecureBoot pre-enrolled keys + vTPM 2.0). **Verified end-to-end:** + +- Boots UEFI/SecureBoot; forced-legacy hands-off install onto a blank disk; OOBE auto-completes. +- `sm-bootstrap` auto-logs in; the Welcome app **auto-launches elevated** and renders the wizard (Mercury theme, bundled fonts). +- All four flavours load from the baked `flavours/*.json`; **Daily-Driver** pre-selected. +- Drove the full wizard: Welcome → Flavour → Account (created `alice` + admin password + BitLocker PIN) → Prefs → Apply → "All Done!". +- Post-apply, offline + on-login assertions: **`alice` created** (Standard daily user) and **`SilverOS Admin` created** (separate elevation account) both appear on the login screen; **`sm-bootstrap` removed**; **no auto-login** (AutoAdminLogon disabled → teardown ran); **BitLocker enabled** (volume encrypted, `-FVE-FS-`). Account creation + bootstrap teardown require elevation, confirming the app runs elevated. + +**Three deployment bugs found + fixed during validation** (only a real run surfaced them): (1) WebView2 user-data folder defaulted to non-writable `Program Files` → redirected to LocalAppData; (2) FirstLogonCommands run un-elevated → bake `ConsentPromptBehaviorAdmin=0` offline + launch via `Start-Process -Verb RunAs`; (3) AccountStep `Next` never enabled because the wizard host didn't re-render on child validity change → added an `OnValidityChanged` callback. Also a separate CI fix: bUnit tests must reference a Razor Class Library, not the MAUI app assembly (else `WindowsAppRuntime` `DllNotFound` on the clean runner). + +**Follow-ups (not v1-pipeline blockers):** +- **BitLocker PIN not enforced** — the device booted with no pre-boot PIN prompt (TPM-only auto-unlock). The intended TPM+PIN protector did not take effect, most likely because the FVE "require startup PIN" policy (`UseAdvancedStartup`/`UseTPMPIN`) wasn't set before `Enable-BitLocker`. The user's PIN currently provides no boot protection — fix before shipping. +- **Apply services don't check PowerShell exit codes** — `AccountService`/`BitLockerService`/`BootstrapService` run `powershell.exe` but ignore `ProcessResult.ExitCode`, so silent failures (like the BitLocker PIN degradation) go unsurfaced. They should check exit codes and fail/log loudly.