Proposal: full reference map, and correct the LTSC autostart assumption
REFERENCES (section 13, was six lines, now a map) Where every referenced thing lives, so the document is usable by someone without today's context: this repo, the PXE server share, shopdb-flask, the on-bay log locations, and the evidence bundles each claim came from. Plus re-derivation recipes - pulling startnet out of boot.wim, extracting customizations.xml from an 8 GB .ppkg without unpacking it, reading the provisioning evtx, and the two validation commands - and the 2026-08-06 commit list. LTSC AUTOSTART - CORRECTED Section 7.1 previously argued PESetup might already auto-start: AutoStartCountDown is 31, disableauto.json is absent, and the operator on 579C144 clicked Next at 11 seconds, so nobody had waited long enough to find out. Per the team's operational experience that is wrong for our media. LTSC builds cannot autostart - the SELECT OS confirmation is mandatory regardless of the countdown, and every image we produce is Windows 11 LTSC 24H2. So the countdown is not a route to zero-touch. That promotes re-implementing the imaging step from a contingency to the actual decision, and the risk table and open questions now frame it as "re-implement, or accept one click per build" - zero-touch being the only thing that requires it. The hands-off test is kept, but only to confirm and record the behaviour first-hand.
This commit is contained in:
@@ -280,22 +280,32 @@ control once 445 is corporate-reachable.)*
|
||||
|
||||
## 7. The PESetup question
|
||||
|
||||
### 7.1 It may already be automatic
|
||||
### 7.1 Autostart does not apply to our media
|
||||
|
||||
`AutoStartCountDown = 31` (decompiled), and **`disableauto.json` is absent** from
|
||||
the media - its *presence* is what disables autostart. Now the observed log:
|
||||
`AutoStartCountDown = 31` exists in the decompiled settings, and
|
||||
`disableauto.json` - whose *presence* disables autostart - is absent from the
|
||||
media. On the surface that suggests a 31-second countdown, and the observed log
|
||||
is consistent with an operator simply clicking before it fired:
|
||||
|
||||
```
|
||||
11:30:07.74 'Selection View' started (LTSC warning displayed)
|
||||
11:30:18.63 Btn 'Next' pressed.
|
||||
```
|
||||
|
||||
The operator clicked at **11 seconds**. Nobody has waited past 31.
|
||||
**However:** per the team's operational experience, **LTSC builds cannot
|
||||
autostart**. The SELECT OS step warns when the media holds an LTSC image
|
||||
("99% of the time only for ShopFloor. Are you sure you want 'LTSC'?") and that
|
||||
confirmation is mandatory regardless of the countdown. Our media is
|
||||
`Windows 11 LTSC 24H2` (`OperatingSystem.json`, build 26100, id 20), so every
|
||||
image we produce hits it.
|
||||
|
||||
**Test first:** one bay, hands off the keyboard, count to 40. If it proceeds,
|
||||
zero-touch needs no new imaging code at all.
|
||||
Consequence: **the countdown is not a route to zero-touch for us.** The 40-second
|
||||
hands-off test is still worth doing once to confirm the behaviour first-hand and
|
||||
record it - but plan on the answer being "it waits".
|
||||
|
||||
### 7.2 If it does hang, re-implementation is tractable
|
||||
That promotes §7.2 from a contingency to the actual decision.
|
||||
|
||||
### 7.2 Re-implementation - now the likely path, and tractable
|
||||
|
||||
Nothing in the mechanism is proprietary - only the data, which we already own and
|
||||
already parse.
|
||||
@@ -319,7 +329,8 @@ being a **warning** rather than a failure.
|
||||
**The cost is ownership, not effort.** `Release.json` points at MCL auto-update
|
||||
URLs, so GE expects this media to self-update. Diverging means tracking their
|
||||
format changes indefinitely, plus a likely compliance conversation about the
|
||||
mandated imaging tool. Hence: run the 40-second test first.
|
||||
mandated imaging tool. Since the LTSC gate means autostart will not save us
|
||||
(§7.1), this is a decision to take deliberately rather than a fallback.
|
||||
|
||||
### 7.3 What we would keep either way
|
||||
|
||||
@@ -395,7 +406,9 @@ silently. A clean slate is the moment to fix that. See `docs/OWNERSHIP.md`.
|
||||
Each phase is useful standing alone. No phase requires the next.
|
||||
|
||||
**Phase 0 - settle the unknowns (hours)**
|
||||
- The 40-second PESetup autostart test
|
||||
- Confirm the LTSC autostart gate first-hand (one bay, hands off, 40 seconds)
|
||||
and record it - expected to wait, per operational experience
|
||||
- Decide: re-implement the imaging step, or accept one click per build
|
||||
- Decide: one image or three
|
||||
- Decide: join at imaging time, at first power-on, or re-inject
|
||||
|
||||
@@ -438,7 +451,7 @@ Each phase is useful standing alone. No phase requires the next.
|
||||
| Dual-homing exposes the PXE server | SSH `pxe/pxe`, SMB, TFTP currently `ALLOW IN Anywhere` | Phase 2 gates everything |
|
||||
| BPRT expiry on shelf stock | silent, indistinguishable from "no network yet" | pick a join strategy (§8.2) and add an explicit expiry check |
|
||||
| Selection UI becomes the new single point of correctness | wrong subtype = wrong PC-DMIS, wrong bay config | re-runnable, server-corrected, audited |
|
||||
| Re-implementing PESetup | ongoing format tracking + compliance | run the autostart test first |
|
||||
| Re-implementing PESetup | ongoing MCL format tracking + a likely compliance conversation | scope it against "one click per build" - zero-touch is the only thing that needs it |
|
||||
| Big payloads over the corporate network | PC-DMIS, FormTracePak ISOs (~2 GB each), Keyence | GE-Enforce supports `smb` / `http` / `inline` per entry - decide per payload |
|
||||
| Three images drift apart | drift caused the 2026-08-06 outage | prefer one image; `share-drift.py` guards what remains |
|
||||
|
||||
@@ -448,7 +461,8 @@ Each phase is useful standing alone. No phase requires the next.
|
||||
|
||||
1. One image or three? What genuinely differs between them?
|
||||
2. Join at imaging time, at first power-on, or re-inject on demand?
|
||||
3. Does PESetup auto-start after 31 seconds?
|
||||
3. Is the LTSC confirmation truly unskippable? (expected yes - it decides
|
||||
whether zero-touch requires re-implementing the imaging step)
|
||||
4. Is replacing the GE-mandated imaging tool acceptable, if it comes to that?
|
||||
5. Does the selection UI run as SYSTEM (no LAPS password), or as an admin user?
|
||||
6. Which payloads stay on SMB and which move to HTTPS?
|
||||
@@ -457,12 +471,122 @@ Each phase is useful standing alone. No phase requires the next.
|
||||
|
||||
---
|
||||
|
||||
## 13. References
|
||||
## 13. Where everything referenced here lives
|
||||
|
||||
- `docs/PESETUP-INTERNALS.md` - decompiled imaging tool behaviour
|
||||
- `docs/OWNERSHIP.md` - who owns what, with the 2026-08-06 collisions
|
||||
- `scripts/preflight.py`, `scripts/lint-unattend.py`,
|
||||
`scripts/lint-driver-catalogue.py`, `scripts/share-drift.py`
|
||||
- `playbook/scripts/preflight.ps1` - bay-side checks
|
||||
- shopdb-flask: `plugins/geenforce/seed_display_scope.py` - the pattern this
|
||||
proposal generalises
|
||||
### 13.1 This repo (`/home/camp/projects/pxe`)
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `docs/PESETUP-INTERNALS.md` | decompiled imaging tool behaviour; the source for every PESetup claim above |
|
||||
| `docs/OWNERSHIP.md` | who owns what, with the 2026-08-06 collisions |
|
||||
| `playbook/startnet.cmd` | the WinPE script this proposal thins out - menus, staging, verify, log harvest |
|
||||
| `playbook/scripts/preflight.ps1` | bay-side checks (secure boot, disk, driver match, media age) |
|
||||
| `playbook/shopfloor-setup/run-enrollment.ps1` | applies the SFLD package via `provtool` |
|
||||
| `playbook/shopfloor-setup/Run-ShopfloorSetup.ps1` | post-boot setup; the enrollment-model comment is here |
|
||||
| `playbook/shopfloor-setup/Fetch-StagingPayload.ps1`, `Verify-And-Heal-Staging.ps1` | first-logon self-heal; read `C:\Enrollment\fetch-source.txt` |
|
||||
| `playbook/shopfloor-setup/BPRT/Select-PCConfig.ps1` | the pre-seed shim (vendor GUI preserved as `-vendor.ps1` on the share) |
|
||||
| `playbook/shopfloor-setup/BIOS/{check-bios.cmd,models.txt}` | firmware matching |
|
||||
| `scripts/preflight.py` | runs every server-side lint in one command |
|
||||
| `scripts/lint-unattend.py` | schema limits: Path 259, CommandLine 1024, Description 256 |
|
||||
| `scripts/lint-driver-catalogue.py` | reimplements `GetDriverByModel` |
|
||||
| `scripts/share-drift.py` | repo vs live share, git-owned vs unreconciled |
|
||||
| `scripts/build-pctype-media.py` | per-PCTYPE media views (retired by Phase 6) |
|
||||
|
||||
### 13.2 PXE server (`pxe@172.16.9.1`)
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `/srv/samba/winpeapps/<image>/Deploy/Control/` | `HardwareDriver.json`, `OperatingSystem.json`, `Media.tag`, `Release.json` |
|
||||
| `/srv/samba/winpeapps/<image>/Deploy/FlatUnattendW10.xml` | the answer file that actually boots machines |
|
||||
| `/srv/samba/winpeapps/_shared/Applications/BPRT/` | the six MCL packages, `Insert-BPRTToPPKG.ps1`, `Start-BulkEnrollOrchestrator.ps1`, `Select-PCConfig*.ps1` |
|
||||
| `/srv/samba/winpeapps/_shared/BIOS/` | firmware EXEs + `models.txt` (served as the `winpeapps_bios` share) |
|
||||
| `/srv/samba/winpeapps/_media/<pctype>/` | per-PCTYPE media views |
|
||||
| `/srv/samba/enrollment/scripts/` | `run-enrollment.ps1`, `preflight.ps1`, `winpe-status-push.ps1` |
|
||||
| `/srv/samba/enrollment/shopfloor-setup/` | per-PC-type trees, `menu.json`, `_ntlars-backups/` (147 `.reg`) |
|
||||
| `/srv/samba/enrollment/shopfloor-setup/gea-shopfloor-waxtrace/bay-config.csv` | 15 bays, FTPak versions |
|
||||
| `/srv/samba/enrollment/installers-post/cmm/cmm-bay-config.csv` | CMM bay -> version, DODA |
|
||||
| `/srv/samba/enrollment/pre-install/udc-backups/` | per-bay UDC settings |
|
||||
| `/srv/samba/enrollment/ppkgs/` | the SFLD package (8.2 GB) |
|
||||
| `/srv/samba/enrollment/imaging-logs/<serial>/` | harvested imaging logs (added 2026-08-06) |
|
||||
| `/var/www/html/win11/sources/boot.wim` | the booted WinPE image |
|
||||
| `/var/log/pxe-imaging/<serial>.json` | per-bay stage history |
|
||||
| `/opt/pxe-webapp/` | Flask webapp (unit `pxe-webapp`, :9009) |
|
||||
| `/etc/dnsmasq.conf`, `/etc/samba/smb.conf` | the binding config §6.2 depends on |
|
||||
|
||||
### 13.3 shopdb-flask (`/home/camp/projects/shopdb-flask`)
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `plugins/geenforce/seed_display_scope.py` | the pattern this proposal generalises - subtype map, server role by IP, sweep |
|
||||
| `plugins/geenforce/client/` | `ShopdbEnforceClient.psm1`, `Invoke-ShopdbEnforce.ps1` |
|
||||
| `shopdb/core/api/` | collector endpoint, dashboard-defaults display-role |
|
||||
|
||||
### 13.4 Evidence behind the claims in this document
|
||||
|
||||
| Path | What it shows |
|
||||
|---|---|
|
||||
| `/home/camp/pxe-images/now/pesetuplog.txt` | PESetup 4.0.0.20 run - media drive, disking, copy, driver selection, the `Btn 'Next'` timing in §7.1 |
|
||||
| `/home/camp/pxe-images/now/debug.txt` | the WinPE console for the failed volume-finder run |
|
||||
| `/home/camp/pxe-images/pxe2/Panther/` | `setupact.log` / `setuperr.log` naming the unattend `Path` failure |
|
||||
| `/home/camp/pxe-images/debug2/` | the autologon registry state and the sysprep-loop timeline |
|
||||
| `/home/camp/pxe-images/debug3/Logs/BPRT/` | the 13 package components, `criticalChecks.json`, `packageInfo.json` |
|
||||
| `/home/camp/pxe-images/debug3/Logs/PPKG/` | the package itself, `provisioning-sessions.json`, the diagnostics evtx |
|
||||
| `/home/camp/pxe-images/debug3/Logs/enrollment.log` | the double run and the rename race in §9 |
|
||||
| `/home/camp/pxe-images/debug3/Logs/FilteredReportIP.log` | proves the bay had no route to Entra (§8.2) |
|
||||
|
||||
### 13.5 On-bay locations (for anyone diagnosing one)
|
||||
|
||||
```
|
||||
C:\Enrollment\ staged payload, pc-type.txt, display-type.txt,
|
||||
pc-config.txt, fetch-source.txt, winpe-staging.log
|
||||
C:\Deploy\Applications\BPRT\ the packages + orchestrator, copied by PESetup
|
||||
C:\Logs\BPRT\<Component>\ per-component package logs (UTF-16)
|
||||
C:\Logs\BPRT\criticalChecks.json PPKG matched / Entra joined / OOBE execution
|
||||
C:\Logs\PPKG\ provisioning diagnostics + session state
|
||||
C:\Logs\SFLD\ DSC deployment, sync_intune, shopfloor-setup
|
||||
C:\Logs\enrollment.log run-enrollment.ps1
|
||||
C:\Windows\Panther\ setupact.log, setuperr.log, unattend.xml, PESetup*.log
|
||||
C:\Windows\Panther\UnattendGC\ oobeSystem pass
|
||||
```
|
||||
|
||||
### 13.6 How to re-derive things
|
||||
|
||||
```bash
|
||||
# read a file off the share
|
||||
sshpass -p pxe ssh -o StrictHostKeyChecking=no pxe@172.16.9.1 'cat <path>'
|
||||
smbclient //172.16.9.1/enrollment -U pxe-upload%pxe -c 'ls'
|
||||
|
||||
# what is actually inside the booted WinPE
|
||||
sudo wimextract /var/www/html/win11/sources/boot.wim 1 \
|
||||
/Windows/System32/startnet.cmd --dest-dir=/tmp/x
|
||||
sudo wimdir /var/www/html/win11/sources/boot.wim 1 | grep -i <name>
|
||||
|
||||
# a .ppkg is a WIM - pull out the spec without extracting 8 GB
|
||||
7z l <pkg>.ppkg
|
||||
7z e <pkg>.ppkg -o<dir> "Multivariant/0/customizations.xml" \
|
||||
"Multivariant/0/Prov/RunTime/0__Accounts_Azure.provxml"
|
||||
|
||||
# provisioning diagnostics (python-evtx is installed)
|
||||
python3 -c "from Evtx.Evtx import Evtx;
|
||||
[print(r.xml()) for r in Evtx('Provisioning-Diagnostics-Admin.evtx').records()]"
|
||||
|
||||
# decompile PESetup - the bundle-extraction recipe is in PESETUP-INTERNALS.md
|
||||
ilspycmd -t <TypeName> PESetup.dll
|
||||
|
||||
# validate before deploying
|
||||
./scripts/preflight.py # every server-side lint
|
||||
./scripts/share-drift.py --diff # repo vs live
|
||||
```
|
||||
|
||||
### 13.7 The 2026-08-06 commits this document draws on
|
||||
|
||||
```
|
||||
dfa026b lint-driver-catalogue c7b1769 build-pctype-media
|
||||
049dd7b startnet per-PCTYPE media d5f7abc BIOS 7020 family
|
||||
385acfe lint-unattend 2b6189f startnet W: wait + honest reporting
|
||||
d04865d PESetup version + LogonCount b96ff7e retire shopfloor-dashboard route
|
||||
36be60e run-enrollment stops renaming 8c21282 staging verify + log harvest
|
||||
d2200e8 preflight (bay + server) 68df59e OWNERSHIP.md + share-drift
|
||||
9d51c0b purpose menu + 3D kiosk a0aceb4 PXESERVER consolidation
|
||||
bb08392 download-drivers case fix
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user