-
Notifications
You must be signed in to change notification settings - Fork 1
Stages
BootstrapMate for Windows recognises two stages, and calls them phases: setupassistant and
userland. They are the only two top-level keys in a manifest. Read this page before you
decide which of your items belongs where, because the split does less than the names suggest.
| Phase | Manifest key | Order | Status key |
|---|---|---|---|
| Setup Assistant | setupassistant |
First | HKLM\SOFTWARE\Cimian\BootstrapMate\Status\SetupAssistant |
| Userland | userland |
Second | HKLM\SOFTWARE\Cimian\BootstrapMate\Status\Userland |
setupassistant runs to completion, then userland starts. Both run inside one invocation of
managedbootstrapinstall.exe, in the same await chain, with nothing in between. There is no
wait for a user session, no reboot, and no second process.
A phase whose key is absent from the manifest is recorded as Skipped and the run moves on.
A phase that is present transitions Starting → Running → Completed, or Failed if the
phase itself throws. Individual item failures do not fail the phase; they are caught and the
loop continues to the next item, so a phase can report Completed with every item failed.
See Logging and Reporting for the full status contract.
Manifest order is not execution order. Before running a phase, items are sorted by a priority
derived from type and name:
| Priority | Matches |
|---|---|
| 1 |
type is msi or exe
|
| 2 |
type is nupkg
|
| 3 |
type is powershell or ps1
|
| 5 | Any other or unreadable type |
| 10 |
powershell/ps1 whose name contains cleanup, clean, wipe, remove, delete, purge, nuclear or maintenance
|
The sort is stable, so manifest order is preserved within a band. When the sort changes
anything, the log says Optimizing package installation order to prevent dependency conflicts.
There is no dependency graph. If item B needs item A, the only lever you have is the priority table above — and the name-based rule at priority 10 will catch a script called "Remove Legacy Agent" whether you meant it to or not.
Every item runs with the token of the process that invoked BootstrapMate. Child installers are
started with UseShellExecute = false, so they inherit that token directly. The CLI's
application manifest requests requireAdministrator, and it re-checks for the Administrators
role at startup, so in practice everything runs elevated.
In a normal MSI deployment that means SYSTEM, in both phases. The MSI's install-time custom
action runs schtasks /Run on a task registered to run as SYSTEM, and the daily 03:00
self-heal task runs as SYSTEM too. Nothing in the userland phase runs as the logged-in user.
If you need per-user work, hand it to the ongoing management agent — see
Handoff to Cimian.
An unelevated --silent run always exits 1, because it refuses to raise a UAC prompt it
cannot display.
There is no OOBE (Out-of-Box Experience) or ESP (Enrollment Status Page) detection anywhere in
this build. Nothing probes enrolment state, session 0, the ESP shell or a console user, and
nothing waits for login. ManagementDetector, despite the name, reads managed settings from
the registry and reports nothing about MDM enrolment.
So what makes a phase a "device phase" is when you invoke the CLI, not anything the CLI decides. Delivering the MSI as a required Win32 app that installs during the ESP gives you a device-context run of both phases; the daily task gives you another device-context run of both phases every morning. If you want work to land after a user logs in, you need something else to invoke BootstrapMate at that point.
Given that, the useful way to read the two phases on Windows is as a coarse ordering
mechanism with separate status reporting, not as two different environments. Put the things
everything else depends on — the management agent, the installer helper, runtimes — in
setupassistant, and the rest in userland.
The macOS build calls these stages, uses the same two key names, and adds a third:
| macOS | Windows | Difference |
|---|---|---|
preflight |
none | A single script that can end the run before it starts. Not implemented here; the key is ignored |
setupassistant |
setupassistant |
Same key, same position. macOS runs it before a user session exists; Windows does not check |
userland |
userland |
macOS blocks until a console user exists, with no timeout, then runs. Windows never waits and never checks |
The other divergence is vocabulary: macOS documentation and code say stage, the Windows code
and registry say phase (InstallationPhase, and a Phase value under each status key). The
JSON key names are identical, so the two are the same word in the manifest and different words
everywhere else. See
https://github.com/bootstrapmate/bootstrapmate-macintosh/wiki/Stages.