feat(welcome): per-role app recipes in the first-boot wizard #17

Merged
SilverLABS merged 11 commits from feat/app-recipes into main 2026-06-09 23:54:29 +00:00
Owner

Summary

Makes the Welcome wizard's role/flavour selection do something: after picking a role, a new Apps step shows grouped, pre-checked app checkboxes (role tools + privacy-trimmed essentials), and the chosen apps are installed via winget during Apply.

  • Catalogwindows/apps/catalog.json (28 apps, schemaVersion:1) loaded by AppCatalog (mirrors FlavourLoader: case-insensitive JSON, graceful degrade to "no apps" on missing/bad file). AppsForRole returns essentials + the role's apps; DefaultSelectionForRole gives the pre-checked set. Shared apps (KeePassXC, VeraCrypt) are single entries with multiple roles.
  • Install engineAppInstaller bootstraps winget (absent in IoT LTSC), then winget install --id … --silent … per selected app, runs optional configure scripts, and is continue-on-failure (a bad app never blocks onboarding). source is swappable to a curated mirror later without touching the UI/engine.
  • WizardAppsStep.razor (grouped checkboxes) inserted after Flavour; WizardState.SelectedApps; defaults seeded on entry from the catalog. Step-index renumbering in Routes.razor is off-by-one clean (verified).
  • ApplyApplyService installs selected apps after account creation, before BitLocker (progress 55→70→75, monotonic). Ordering is locked by an ApplyServiceTests assertion (modules→accounts→apps→bitlocker→bootstrap).
  • Buildbuild.ps1 stages windows/apps/ (catalog + configure/ + bootstrap-winget.ps1) next to the Welcome app, mirroring the flavours copy, with a bake-guard that throws if catalog.json didn't land.
  • ungoogled-chromium ships a configure script enabling the Chrome Web Store source + ForceGoogleSafeSearch.

Spec: windows/docs/superpowers/specs/2026-06-09-wizard-app-recipes-design.md · Plan: windows/docs/superpowers/plans/2026-06-10-wizard-app-recipes.md

Built subagent-driven: each task implemented TDD + spec-compliance review + code-quality review; final whole-feature integration review confirmed the flavour-id ↔ role-string match and end-to-end data flow.

Test Plan

  • dotnet test windows/welcome/SilverOS.Welcome.sln -c Release36/36 pass (incl. install-ordering + catalog/installer unit tests)
  • dotnet build windows/welcome/src/SilverOS.Welcome.App -c Release0 warnings / 0 errors (full MAUI app)
  • catalog.json parses, 28 unique ids; build.ps1 + both .ps1 scripts parse clean (ASCII-only)
  • VM/hardware e2e (next install cycle): pick a role → Apps step shows grouped pre-checked apps → Apply installs them via winget. Note: in-VM winget install needs network; the test VM's HVCI-blocked NIC means real install verification happens on the virtio rig or Pocket 4 hardware.

Known follow-ups (not in this PR)

  • Surface an "Installed N of M (failed: …)" summary on the Done step (spec §3d/§6) — install result is currently fire-and-forget; continue-on-failure already works.
  • WDAC allow-listing of installed apps for Privacy-Max/Journalist enforce mode (spec §2 caveat).
  • Curated SilverMetal mirror (source.mirror) for the air-gap end-state.

🤖 Generated with Claude Code

## Summary Makes the Welcome wizard's role/flavour selection **do something**: after picking a role, a new **Apps** step shows grouped, pre-checked app checkboxes (role tools + privacy-trimmed essentials), and the chosen apps are installed via winget during Apply. - **Catalog** — `windows/apps/catalog.json` (28 apps, `schemaVersion:1`) loaded by `AppCatalog` (mirrors `FlavourLoader`: case-insensitive JSON, graceful degrade to "no apps" on missing/bad file). `AppsForRole` returns essentials + the role's apps; `DefaultSelectionForRole` gives the pre-checked set. Shared apps (KeePassXC, VeraCrypt) are single entries with multiple `roles`. - **Install engine** — `AppInstaller` bootstraps winget (absent in IoT LTSC), then `winget install --id … --silent …` per selected app, runs optional `configure` scripts, and is **continue-on-failure** (a bad app never blocks onboarding). `source` is swappable to a curated mirror later without touching the UI/engine. - **Wizard** — `AppsStep.razor` (grouped checkboxes) inserted after Flavour; `WizardState.SelectedApps`; defaults seeded on entry from the catalog. Step-index renumbering in `Routes.razor` is off-by-one clean (verified). - **Apply** — `ApplyService` installs selected apps after account creation, before BitLocker (progress 55→70→75, monotonic). Ordering is locked by an `ApplyServiceTests` assertion (`modules→accounts→apps→bitlocker→bootstrap`). - **Build** — `build.ps1` stages `windows/apps/` (catalog + `configure/` + `bootstrap-winget.ps1`) next to the Welcome app, mirroring the flavours copy, with a bake-guard that throws if `catalog.json` didn't land. - ungoogled-chromium ships a `configure` script enabling the Chrome Web Store source + `ForceGoogleSafeSearch`. Spec: `windows/docs/superpowers/specs/2026-06-09-wizard-app-recipes-design.md` · Plan: `windows/docs/superpowers/plans/2026-06-10-wizard-app-recipes.md` Built subagent-driven: each task implemented TDD + spec-compliance review + code-quality review; final whole-feature integration review confirmed the flavour-id ↔ role-string match and end-to-end data flow. ## Test Plan - [x] `dotnet test windows/welcome/SilverOS.Welcome.sln -c Release` → **36/36 pass** (incl. install-ordering + catalog/installer unit tests) - [x] `dotnet build windows/welcome/src/SilverOS.Welcome.App -c Release` → **0 warnings / 0 errors** (full MAUI app) - [x] `catalog.json` parses, 28 unique ids; `build.ps1` + both `.ps1` scripts parse clean (ASCII-only) - [ ] **VM/hardware e2e** (next install cycle): pick a role → Apps step shows grouped pre-checked apps → Apply installs them via winget. Note: in-VM winget install needs network; the test VM's HVCI-blocked NIC means real install verification happens on the virtio rig or Pocket 4 hardware. ## Known follow-ups (not in this PR) - Surface an "Installed N of M (failed: …)" summary on the Done step (spec §3d/§6) — install result is currently fire-and-forget; continue-on-failure already works. - WDAC allow-listing of installed apps for Privacy-Max/Journalist enforce mode (spec §2 caveat). - Curated SilverMetal mirror (`source.mirror`) for the air-gap end-state. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
SilverLABS added 11 commits 2026-06-09 23:54:17 +00:00
Per-role app-install picker for the Welcome wizard: catalog.json + AppsStep + winget
install engine (phased, swappable source for a future curated mirror). Stack stays
auto-installed; picker adds role apps + privacy-trimmed essentials. Approved in
brainstorming. Next: writing-plans.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Insert AppsStep as wizard index 2 (renumbering Account/Prefs/Apply/Done
to 3-6), load the app catalog alongside flavours, seed the per-role
default selection on entering the step, and register IAppCatalog in DI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(apps): catalog.json + chromium configure + winget bootstrap + build staging
All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (pull_request) Successful in 6m36s
260023a1a5
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SilverLABS merged commit 129b8741fd into main 2026-06-09 23:54:29 +00:00
SilverLABS deleted branch feat/app-recipes 2026-06-09 23:54:29 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SilverLABS/SilverMetal#17