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>
- 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>
powershell.exe -File binds a single-quoted comma list like '00','03','05' as ONE string element,
not a [string[]] array, so Invoke-Hardening.ps1's -contains filter matched nothing and all
hardening modules were silently skipped.
Fix: adopt a CSV-split contract — Invoke-Hardening.ps1 now accepts [string]$Modules and splits
on ',' internally ($ModuleList = $Modules -split ','); ApplyService passes a bare CSV token
(e.g. 00,03,05) with no surrounding quotes. Empirically verified via ProcessStartInfo: candidate
(a) '00','03','05' → COUNT=1 (bug); candidate (b) 00,03,05 → single string, correctly split by
the script; candidate (c) space-separated → PS positional-parameter error. PARSE OK confirmed.
Adds ApplyServiceHardeningIntegrationTests: copies the real Invoke-Hardening.ps1 into a temp
dir with harmless dummy 0*.ps1 stubs, runs ApplyService with the real ProcessRunner for modules
["00","05"], and asserts ran.txt contains RAN 00 and RAN 05 but NOT RAN 03 or RAN 07.
Test fails on the old encoding and passes with the fix (regression-checked).