Record who owns what, and report repo-vs-share drift

OWNERSHIP.md
Every expensive bug in this pipeline has had one shape: two systems setting the
same thing, last writer winning silently. Four happened on 2026-08-06 alone -
computer name (package vs run-enrollment), drive letters (PESetup vs a volume
finder), enrollment (package vs an at-logon -ManualFallback task that syspreped
finished machines), kiosk URLs (GE-Enforce vs site-config). Each is written down
with the evidence so the next person deletes a writer instead of adding one.

share-drift.py
The share is production and the repo is meant to describe it, but drift runs both
ways: live hand-edits nobody committed, and repo fixes never deployed. The
unattend outage lived only on the share while the repo copy was fine, and nothing
compared them.

Each mapped pair is classified. git-owned means the repo wins and the pair must
match - those fail the run. unreconciled means the two have genuinely diverged
and nobody has decided; reported, not failed. The unattends are unreconciled on
purpose: live is ~17 KB against ~12 KB in the repo, so a blind push would regress
production. Reads over SSH via base64 so BOM and CRLF survive the hop.

First run: 8 git-owned pairs all match, 4 known-unreconciled.

Run-ShopfloorSetup.ps1
Corrects a comment that was actively misleading. It claimed shopfloor PCs are
"vanilla by design" and that the orchestrator runs -ManualFallback to skip BPRT
injection and the package entirely. Shopfloor bays DO enrol - the SFLD package
joins Entra with its BPRT token and a human assigns the device category in
Intune. -ManualFallback runs sysprep /oobe /reboot, which is why wiring it to an
at-logon task destroyed the deployment chain.

The absent Entra wait is still correct, for a different reason: at that point the
bay is on the isolated PXE LAN with no route to Entra (579C144 held 172.16.9.81
and 172.24.19.142, neither in the production ranges). sync_intune retries until
the tech re-cables. "Entra ID Joined: false" right after imaging is normal.
This commit is contained in:
cproudlock
2026-08-06 14:28:16 -04:00
parent d2200e8522
commit 68df59e117
3 changed files with 293 additions and 3 deletions

View File

@@ -62,7 +62,7 @@ cmd /c "shutdown /a 2>nul" *>$null
# done work and continues from where it left off.
#
# Also top up AutoLogonCount so the SupportUser autologon budget
# (LogonCount=7 from unattend XML) survives extra unplanned reboots.
# (LogonCount=12 from unattend XML) survives extra unplanned reboots.
$selfResumeKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce'
$selfResumeName = 'ResumeRunShopfloorSetup'
$selfResumeCmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "' + $PSCommandPath + '"'
@@ -94,9 +94,51 @@ $enrollDir = "C:\Enrollment"
$typeFile = Join-Path $enrollDir "pc-type.txt"
$setupDir = Join-Path $enrollDir "shopfloor-setup"
# NOTE: there is deliberately NO wait for an Entra join here - but NOT because
# shopfloor bays skip enrollment. They do enrol: the SFLD provisioning package
# joins Entra using the BPRT token it carries, and a human then assigns the
# device category in Intune.
#
# The wait is absent because the join cannot happen yet. At this point the bay is
# still on the isolated PXE LAN with no route to Entra - observed on 579C144
# 2026-08-06, holding 172.16.9.81 and 172.24.19.142, neither in the production
# ranges. sync_intune retries every 30 seconds until the tech re-cables to
# production, which is the right place to wait. An earlier version blocked here
# for 45 minutes and then warned about a failure that had not happened.
# "Entra ID Joined: false" in C:\Logs\BPRT\criticalChecks.json straight after
# imaging is therefore NORMAL, not a fault.
#
# CORRECTION (2026-08-06): this comment previously claimed shopfloor PCs are
# "vanilla by design" and that the orchestrator runs with -ManualFallback to skip
# BPRT injection and the package entirely. That was wrong and dangerous.
# -ManualFallback runs sysprep /oobe /reboot, so wiring it to an at-logon task
# syspreped finished machines seconds after autologon and destroyed the
# deployment chain. See docs/OWNERSHIP.md.
if (-not (Test-Path $typeFile)) {
Write-Host "No pc-type.txt found - skipping shopfloor setup."
exit 0
# A missing pc-type.txt means one of two very different things, and the old
# blanket "skip + exit 0" hid the bad one for weeks: four Display bays sat
# at imaging stage 2 with a green exit code and nobody noticed.
# - no C:\Enrollment at all -> this machine was never staged by WinPE
# (pre-imaging, or the staging block never ran). That is a FAILURE on a
# machine that has clearly just been imaged, so say so loudly.
# - C:\Enrollment exists but no pc-type.txt -> staging ran and the write
# failed. Also a failure.
$stagingLog = Join-Path $enrollDir 'winpe-staging.log'
$detail = if (Test-Path $enrollDir) {
"C:\Enrollment exists but pc-type.txt is missing - WinPE staging ran but did not write it. Check $stagingLog."
} else {
"C:\Enrollment does not exist - WinPE staging never ran. The Windows volume was probably not found in startnet.cmd, so pc-type.txt, the enrollment package and shopfloor-setup were ALL skipped."
}
Write-Host ""
Write-Host "================================================================"
Write-Host " FAILED: no pc-type.txt at $typeFile"
Write-Host " $detail"
Write-Host " Shopfloor setup cannot run. This PC is imaged but NOT configured."
Write-Host "================================================================"
Write-Host ""
Report-Stage -Stage 'Run-ShopfloorSetup: FAILED - no pc-type.txt' -Index 2 -Status 'failed' -Error_ $detail
exit 1
}
$pcType = (Get-Content $typeFile -First 1).Trim()