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>
A prior aborted build left a DISM image mounted in the fixed WorkDir,
locking install.wim and breaking the Stage 2 extract clean-up. Add a
Stage 0 that discards any orphaned SilverMetal mounts + loaded hives
before recreating the work dirs, and run CI in an ephemeral per-job
RUNNER_TEMP WorkDir so concurrent/aborted runs can't collide.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the full-viewport .wizard rule with a fixed-inset frosted-glass card
(backdrop-filter blur, semi-transparent surface, rounded corners, inset shadow)
so the Mercury void/gradient wall shows behind and around the card. Adds
@keyframes sm-rise entrance animation and a body::after SILVERMETAL wordmark
watermark on the wall. Targets the real .wizard class in SilverOS.Welcome.UI/
Components/Routes.razor — no App-project markup touched.
Delete wwwroot/css/silvermetal.css (sm-* selectors targeting no markup),
remove its <link> from index.html, and restore App-project stock Layout/Pages
components (MainLayout, NavMenu, Home) to their pre-Phase-C state at 2d8b651.
These files are unused dead-code — the wizard shell lives in SilverOS.Welcome.UI.
Phased TDD plan: A (branding module, hardware-free), B (kiosk: Shell
Launcher v2 + Keyboard Filter), C (MAUI fullscreen glass presentation),
D (build integration + VM e2e). Bite-sized tasks with complete code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Design for SilverMetal Windows first-boot: declarative branding build
(4 layers baked offline into the WIM, shared dual-mode module), hardened
onboarding kiosk (Shell Launcher v2 + Keyboard Filter for the one-time
sm-bootstrap session), and the Hybrid fullscreen glass-card presentation
for the Welcome app. Fills the empty Invoke-Brand stub (M4 branding).
Approved in brainstorming. Next: writing-plans.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AccountStep now exposes OnValidityChanged EventCallback<bool> and fires it at the end of every Validate() call (including OnInitialized). Routes.razor drops the @ref/IsValid polling pattern in favour of _accountValid updated via the callback + StateHasChanged, matching the existing OnRunningChanged pattern used by ApplyStep. Adds 5 bUnit regression tests covering: initial-invalid, all-valid, re-invalid on clear, short/non-numeric PIN, and pre-populated state on Back→Forward re-mount.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds Invoke-PublishWelcome (dotnet publish win-x64 self-contained, runs pre-mount)
and Copy-WelcomePayload (copies publish output + flavours/*.json into $mount while
install.wim is open) called from Invoke-ServiceWim's try block. Both are gated on
SILVERMETAL_WELCOME_ENABLED != '0' (enabled by default). Hardening staging unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename the unattend LocalAccount from silvermetal → sm-bootstrap
(Administrators), add a one-time AutoLogon and a FirstLogonCommands
entry that launches SilverOS.Welcome.App.exe on first boot. The
Welcome app's ApplyService tears down AutoAdminLogon + removes
sm-bootstrap on successful onboarding.
- ApplyStep: guard StartAsync against double-invocation (_running check at top)
- ApplyService: replace raw StdErr dump with scrubbed message (exit code + first non-empty line, ≤200 chars)
- ApplyStep: SanitiseForDisplay strips newlines and caps error at 200 chars before rendering
- ApplyStep: add OnRunningChanged EventCallback<bool>; Routes.razor disables Back while _applyRunning
- Routes.razor: AdvanceToDone uses _stepTitles.Length - 1 instead of magic literal 5
- app.css: replace Google Fonts CDN @import with local @font-face rules; bundle DM Mono (300/400/500 + italic 300) and Inter (300/400/500) latin woff2 files under wwwroot/fonts/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds SilverOS.Welcome.App (net9.0-windows10.0.19041.0 only), registers
all Core services in MauiProgram.cs, and introduces WizardState scoped
service for the wizard host.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>