Live e2e: in the sm-bootstrap session the taskbar showed and Win/Start worked.
- Keyboard Filter EXEMPTS administrators by default and sm-bootstrap is an admin, so
Win/Start/Alt-Tab etc. were never blocked. Set WEKF_Settings
DisableKeyboardFilterForAdministrators=false so the filter applies to it.
- Auto-hide the taskbar (default-user StuckRects3, inherited by sm-bootstrap) so it
doesn't peek over the fullscreen wizard.
- TearDownAsync now Disable-LocalUser's sm-bootstrap in-session (immediate) so it's
unusable at once; the deferred SYSTEM task still deletes it on next boot (SAM-confirmed
the delete works now).
Verified: Configure-Kiosk parses under Windows PowerShell 5.1 (ASCII-clean); welcome 29/29.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VM e2e findings on the real-user desktop:
1. Lock/login screen + wallpaper NOT branded (OEM About WAS) — Windows resets the
offline-baked personalization (PersonalizationCSP / default-user wallpaper / FVE)
during OOBE, same class as the UAC reset. Fix: stage windows/branding/ into the
image and re-run Apply-Branding -Mode Online from SetupComplete (post-OOBE, as
SYSTEM) where it sticks. OEM About re-asserted harmlessly.
2. sm-bootstrap account still present after onboarding — TearDownAsync's in-session
Remove-LocalUser no-ops (can't delete the account you're logged in as). Fix: keep
the best-effort in-session attempt, but DEFER the real removal to a SYSTEM
AtStartup scheduled task that runs on next boot (sm-bootstrap not logged on),
removes the account + Win32_UserProfile, then deletes itself.
(Network 'no adapter' in the VM was a Proxmox NIC-model regression to virtio — fixed
by switching the VM to Intel e1000; not a SilverMetal change.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5th VM e2e: with the kiosk fully working mechanically (SL engages, silent UAC,
app launches fullscreen as the shell), the MAUI/WebView2 wizard STILL renders
blank — WebView2 never initializes when the app is the bare Shell Launcher shell
with no Explorer (the same app rendered fine in the earlier build launched with
Explorer present). Operator decision: pivot.
- autounattend.xml: restore FirstLogonCommands to launch the wizard elevated over
the normal (Explorer) first-logon session — where WebView2 works.
- Configure-Kiosk.ps1: drop Shell-Launcher-as-shell entirely; keep the lockdown —
Keyboard Filter (Win/Start/lock/task-switch/Task-Mgr/Alt+F4), DisableTaskMgr /
LockWorkstation / FastUserSwitch, and silent-elevation UAC. The wizard runs
fullscreen-topmost over the locked-down Explorer (covers the taskbar).
- RevertKioskAsync: disable the Keyboard Filter rules for the real user (no SL to
undo); keep escape-policy + secure-UAC restore. Tests updated.
Keeps the diagnostics from #10 (welcome.log) to confirm the wizard renders.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4th e2e showed a UAC consent prompt for the unsigned Welcome app — the offline-baked
ConsentPromptBehaviorAdmin=0 is reset by Windows during OOBE. Re-assert it (and
PromptOnSecureDesktop=0) ONLINE in Configure-Kiosk.ps1, which runs right before the
sm-bootstrap autologon, so 'Start-Process -Verb RunAs' elevates silently. RevertKioskAsync
restores SECURE UAC (ConsentPromptBehaviorAdmin=2, PromptOnSecureDesktop=1) for the real user.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3rd VM e2e: Shell Launcher now ENGAGES (kiosk shell up, no Explorer), but the
launcher's 'Start-Process -LiteralPath ...' errored — Start-Process has no
-LiteralPath parameter (that was an unvalidated review tweak; the proven form
is -FilePath). So the kiosk shell ran but the Welcome app never started. Revert
both the launcher and the RunOnce fallback to -FilePath. Single-quote escaping
of the path is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2nd VM e2e: Shell Launcher config still failed with 'Type mismatch for parameter
DefaultAction'. WESL_UserSetting.SetCustomShell/SetDefaultShell take sint32 (Int32)
DefaultAction, but we passed [uint32]0. The fail-open rollback worked (no brick,
booted to Explorer) but the kiosk never engaged. Pass [int32]0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VM e2e caught a reboot loop: Configure-Kiosk used `Invoke-CimMethod -InputObject $wesl`
for SetDefaultShell/SetCustomShell, but WESL_UserSetting exposes STATIC methods and
Get-CimInstance returns null — so those calls threw "InputObject is null" while the
class-level SetEnabled($true) had already succeeded. Result: Shell Launcher enabled with
NO shell configured -> every logon (incl. OOBE defaultuser0) gets a broken shell -> the
"Why did my PC restart?" OOBE loop.
Fix: call SetEnabled/SetDefaultShell/SetCustomShell all class-level (-Namespace/-ClassName).
Setting the DEFAULT shell to explorer.exe is what keeps OOBE/normal logons alive; only
sm-bootstrap gets the kiosk launcher. Added GetCustomShell verification + a fail-open
rollback (SetEnabled false + RunOnce launch of the Welcome app) so a WMI hiccup can never
brick the box again. Same class-level fix applied to BootstrapService.RevertKioskAsync.
Found via VM 102 disk logs (silvermetal-firstboot.log + silvermetal-kiosk.log).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VM runtime test (offline disk mount) revealed SetupComplete.cmd ran but its inline
multi-line `powershell -Command` (cmd ^-continuation + nested escaped quotes) failed
to parse ("string is missing the terminator") -> the §A-H modules never executed.
Offline CI assertions only proved the files were BAKED, not that they RUN.
Fix: move the module runner into hardening/Invoke-Hardening.ps1 and call it with
-File (no cmd quoting). Runner runs 00*..08* in order then Verify (writes
verify-report.json in-line as SYSTEM; reboot/PIN-dependent gates show pending).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>