docs(windows): SilverOS Welcome app spec (v1)
All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (push) Successful in 3m42s
All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (push) Successful in 3m42s
First-logon Blazor Hybrid (MAUI) onboarding app: bootstrap auto-login -> wizard (persona->flavour, account + BitLocker PIN, prefs) -> apply via the existing §A-H PowerShell modules per a JSON flavour manifest -> create real account, enrol BitLocker, self-destruct bootstrap. Resolves the repo-throwaway-password and interactive-PIN gaps. v1 = interactive auto-launch only; silent pre-baked mode + fleet enrolment + Linux-shared model deferred. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
109
windows/welcome-app-spec.md
Normal file
109
windows/welcome-app-spec.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# SilverOS Welcome — Specification (v1)
|
||||
|
||||
> **Status**: design approved 2026-06-09. Part of **SilverMetal Enhanced — Windows**.
|
||||
> First-logon onboarding app that turns a hardened image into a personalised device:
|
||||
> the user picks a **flavour**, creates their **account + BitLocker PIN**, and the app
|
||||
> applies the chosen configuration by orchestrating the existing §A–H hardening modules.
|
||||
|
||||
Bound by [`hardening-spec.md`](hardening-spec.md), [`iso-builder.md`](iso-builder.md), and the SilverMetal [`../docs/design-principles.md`](../docs/design-principles.md).
|
||||
|
||||
## 1. Purpose & positioning
|
||||
|
||||
Today the image applies **one fixed** hardening config at first boot (`SetupComplete.cmd` → §A–H modules). The Welcome app makes "SilverMetal Enhanced — Windows" a **selectable platform**: a friendly first-logon wizard where the buyer chooses *what the device is for* (a **flavour** = config profile + app set), sets up their own account, and the device configures itself accordingly.
|
||||
|
||||
It also resolves two real gaps found during VM validation:
|
||||
- **No throwaway credential in the public repo** — the committed account becomes a locked **bootstrap** account that **self-destructs** after onboarding.
|
||||
- **BitLocker PIN enrollment** — collected interactively in the wizard (BitLocker TPM+PIN can't be fully automated; this is the right place for it).
|
||||
|
||||
**v1 = interactive auto-launch only.** A fully-silent pre-baked SKU mode is a later phase (§8).
|
||||
|
||||
## 2. Architecture & components
|
||||
|
||||
A **Blazor Hybrid (.NET MAUI + WebView2)** desktop app, published **self-contained** (bundled runtime) and baked into the image. Reuses SilverSHELL components + the SilverDESK "Welcome" wizard aesthetic (Mercury). Four well-bounded units:
|
||||
|
||||
| Unit | Responsibility | Depends on |
|
||||
|---|---|---|
|
||||
| **Welcome.Shell** | MAUI host + wizard UI (the steps in §3). What the user sees. | Welcome.Flavours, Welcome.Apply |
|
||||
| **Welcome.Flavours** | Load + validate flavour manifests from `windows/flavours/*.json` (baked into the image). | manifest schema |
|
||||
| **Welcome.Apply** | Orchestrator: run the §A–H PowerShell modules per the manifest, install the app set, create the real account, enrol BitLocker, tear down the bootstrap. | PowerShell modules, Windows account/BitLocker APIs |
|
||||
| **Welcome.Bootstrap** | Answer-file / AutoLogon / RunOnce wiring that auto-logs-in and launches the app. | autounattend, build.ps1 |
|
||||
|
||||
Each unit is independently testable: Welcome.Apply can run headless against a flavour manifest (no UI); Welcome.Flavours validates manifests without applying; the Shell can be run with a mock applier.
|
||||
|
||||
## 3. Boot → onboard → handoff flow (bootstrap lifecycle)
|
||||
|
||||
1. **Image** ships a **locked bootstrap admin account** (`sm-bootstrap`) with **AutoLogon (LogonCount=1)** and a RunOnce/custom-shell that launches the Welcome app in a kiosk-ish session (no taskbar/Explorer escape). The §A–H modules **no longer run from `SetupComplete`** — `SetupComplete` only stages the payload; the Welcome app applies it.
|
||||
2. **First logon** (auto, as `sm-bootstrap`) → Welcome app launches. Wizard steps:
|
||||
- **Welcome** — brand intro.
|
||||
- **What's this device for?** — persona → selects a **flavour** (cards: Privacy-Max / Daily-Driver / Journalist / Developer).
|
||||
- **Create your account** — username + password (+ confirm).
|
||||
- **Secure this device** — set a **BitLocker PIN** (≥ flavour-min).
|
||||
- **Preferences** — a few toggles (e.g. telemetry-floor confirmation, browser default, timezone).
|
||||
- **Apply** — progress UI while Welcome.Apply runs.
|
||||
- **Done** — "restart to finish."
|
||||
3. **Apply** (Welcome.Apply, elevated):
|
||||
- run the flavour's **hardening modules** (per manifest) + **app-set** install;
|
||||
- **create the real account** (admin) with the entered credentials;
|
||||
- **enrol BitLocker TPM+PIN** with the entered PIN;
|
||||
- remove AutoLogon + the RunOnce.
|
||||
4. **Self-destruct + reboot** — delete the `sm-bootstrap` account, then **reboot** into the real account (also activates VBS/Credential Guard, which need a reboot).
|
||||
|
||||
## 4. Flavour manifest model
|
||||
|
||||
A flavour is a JSON file in `windows/flavours/` baked into the image:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "privacy-max",
|
||||
"label": "Privacy-Max",
|
||||
"description": "Maximum lockdown. Everything Microsoft exposes, turned to its tightest.",
|
||||
"hardening": {
|
||||
"modules": ["00","01","02","03","04","05","06","07"], // which §A-H modules
|
||||
"params": { "wdac": "enforce", "telemetry": "security" } // per-module overrides
|
||||
},
|
||||
"appSet": ["SilverBrowser","SilverVPN","SilverKeys","SilverDuress"],
|
||||
"settings": { "defaultBrowser": "SilverBrowser", "autoLock": 120 }
|
||||
}
|
||||
```
|
||||
|
||||
**Welcome.Apply orchestrates the existing PowerShell §A–H modules** per `hardening.modules`/`params` — PowerShell stays the single source of truth for *what hardening does* (also reusable headless for the future silent SKU). *(Rejected alternative: re-implement hardening in a .NET library — cleaner for an all-.NET app but duplicates the proven logic.)* The Shell renders one card per manifest; adding a flavour = adding a JSON file.
|
||||
|
||||
**Starter flavours (v1):** Privacy-Max, Daily-Driver, Journalist, Developer — differing in hardening strictness (e.g. WDAC enforce vs audit, relaxed dev tooling) and app set.
|
||||
|
||||
## 5. Account & BitLocker integration
|
||||
|
||||
- The **real account** is created as a local **Administrator** (personal-device owner). *(Standard-user/least-privilege as a flavour option is a later enhancement — persona was chosen as the role axis, not privilege.)*
|
||||
- **BitLocker TPM+PIN** is enrolled with the user's PIN during Apply (`Enable-BitLocker -TpmAndPinProtector`), satisfying module C's interactive step. Recovery key stored offline / shown to the user (never cloud-escrowed) per `hardening-spec.md` §C.
|
||||
- The **bootstrap account** is admin only so the app can run hardening + manage accounts; it is deleted in step 4 so no standing extra admin remains.
|
||||
|
||||
## 6. Build & repo integration
|
||||
|
||||
- New **`windows/welcome/`** (MAUI app source) + **`windows/flavours/*.json`**.
|
||||
- **`build.ps1`** gains a stage that drops the **published Welcome app + flavours** into the image (`/Program Files/SilverMetal/Welcome` + a flavours dir), and wires the bootstrap (AutoLogon + RunOnce) via the answer file / offline registry.
|
||||
- The **answer file** switches from "create `silvermetal`/`open sesame`" to "create **`sm-bootstrap`** + AutoLogon + launch Welcome." `SetupComplete.cmd` stops running the §A–H modules directly (the Welcome app runs them).
|
||||
- A repo switch (**`vars.SILVERMETAL_WELCOME_ENABLED`**, default on) controls whether the build wires onboarding or falls back to today's direct-hardening behaviour (so the current validated path remains available).
|
||||
|
||||
## 7. Testing
|
||||
|
||||
- **Welcome.Flavours**: unit tests validate every shipped manifest against the schema.
|
||||
- **Welcome.Apply**: headless run against each flavour on the VM (reuses the SLAB01 VM-test harness) → assert the firstboot/apply log shows the expected modules + the real account + BitLocker protector + bootstrap removed.
|
||||
- **Welcome.Shell**: bUnit-style component tests for step navigation/validation; a manual VM pass for the full wizard.
|
||||
- The existing **offline ISO assertions** extend to check the Welcome app + flavours are baked.
|
||||
|
||||
## 8. v1 scope
|
||||
|
||||
**In:** interactive auto-launch onboarding; persona→flavour; account + BitLocker-PIN creation; prefs; apply-via-PowerShell-modules; bootstrap self-destruct; 3–4 starter flavours; build/answer-file wiring + `WELCOME_ENABLED` switch.
|
||||
|
||||
**Out (later phases):**
|
||||
- **Silent pre-baked mode** (apply a baked flavour + pre-set account with no wizard — the "we did everything for you" SKU).
|
||||
- **SilverDESK / fleet enrollment** role.
|
||||
- **Shared flavour model with the Linux line.**
|
||||
- **Real Stack app installs** — the app-set installer is wired, but Stack entries remain stubs until native Windows Stack builds exist (M4).
|
||||
- **Standard-user/least-privilege** real account option.
|
||||
|
||||
## 9. Open questions / risks
|
||||
|
||||
- **WebView2 + .NET runtime in the image** — confirm WebView2 Evergreen is present on IoT Enterprise LTSC (or bundle the fixed-version runtime); self-contained publish covers .NET.
|
||||
- **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).
|
||||
- **Naming** — "SilverOS Welcome" vs "SilverMetal Welcome" (the program is SilverMetal; "SilverOS" is the floated umbrella). Cosmetic; decide before first release.
|
||||
Reference in New Issue
Block a user