Monitor + imaging: per-phase sub-stages within idx=7

Monitor's Get-Snapshot already tracks Phase 1-5 (Intune Registration,
Device Configuration, Software Deployment, Credentials, Lockdown).
The webapp dashboard only saw a single idx=7 push for the entire
post-PPKG / pre-lockdown window, so the friendly label couldn't
reflect "where is this bay actually". Operator looking at the
dashboard had no idea whether to assign category or hit ARTS for
lockdown next.

Monitor now pushes additional idx=7 entries as it crosses Phase
boundaries:
 - On DeviceId capture: "Intune Device ID captured" (existing)
 - On Phase 2 done (SFLD policy delivered = category was assigned):
   "Phase 2 SFLD policy delivered (device configuration)"
 - On Phase 1-4 all complete: "Phases 1-4 complete - ready for
   lockdown (ARTS request)"
 - On lockdown done: idx=8 (existing)

imaging.html maps the stage_string substring to friendly labels:
 - default idx=7         -> "Registered - assign category"
 - 'sfld policy' / 'phase 2' -> "Phase 2 - device configuration"
 - 'credentials' / 'phase 4' -> "Phase 3 / 4 - DSC + credentials"
 - 'ready for lockdown' / 'request lockdown' -> "Ready - request
                              lockdown" (hint: click ARTS request)

Operator now knows exactly when to act vs when to wait.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-05-15 07:39:20 -04:00
parent 220c5db5b9
commit 3385bc87aa
2 changed files with 49 additions and 2 deletions

View File

@@ -186,6 +186,8 @@ $script:cache = @{
EnrollmentId = $null EnrollmentId = $null
DeviceId = $null DeviceId = $null
DeviceIdReported = $false DeviceIdReported = $false
SfldPolicyPushed = $false
CredsReadyPushed = $false
LockdownCompletePushed = $false LockdownCompletePushed = $false
InternetAccessDeleted = $false InternetAccessDeleted = $false
} }
@@ -1240,6 +1242,35 @@ try {
while ($true) { while ($true) {
$snap = Get-Snapshot $snap = Get-Snapshot
# Push sub-stage transitions to PXE dashboard so the operator sees
# whether the bay is waiting on category assignment, or has
# progressed past it. idx stays 7 across all three; the stage
# string drives the friendly label in imaging.html.
if (-not $script:cache.SfldPolicyPushed -and
$snap.Phase2.SfldRoot -and $snap.Phase2.FunctionOk -and $snap.Phase2.SasTokenOk) {
if (Get-Command Send-PxeStatus -ErrorAction SilentlyContinue) {
try {
Send-PxeStatus -Stage 'Monitor-IntuneProgress: Phase 2 SFLD policy delivered (device configuration)' `
-StageIndex 7 -StageTotal 8 `
-IntuneDeviceId $script:cache.DeviceId -ErrorAction SilentlyContinue
$script:cache.SfldPolicyPushed = $true
} catch {}
}
}
if (-not $script:cache.CredsReadyPushed -and
$snap.Phase4.CredsPopulated -and
$snap.Phase3.InstallComplete -and
$snap.Phase2.SfldRoot -and $snap.Phase2.FunctionOk -and $snap.Phase2.SasTokenOk) {
if (Get-Command Send-PxeStatus -ErrorAction SilentlyContinue) {
try {
Send-PxeStatus -Stage 'Monitor-IntuneProgress: Phases 1-4 complete - ready for lockdown (ARTS request)' `
-StageIndex 7 -StageTotal 8 `
-IntuneDeviceId $script:cache.DeviceId -ErrorAction SilentlyContinue
$script:cache.CredsReadyPushed = $true
} catch {}
}
}
# Retry QR code every cycle until it actually renders. dsregcmd # Retry QR code every cycle until it actually renders. dsregcmd
# may report AzureAdJoined=YES before DeviceId is populated, so # may report AzureAdJoined=YES before DeviceId is populated, so
# a single-shot refresh misses the window. # a single-shot refresh misses the window.

View File

@@ -49,8 +49,8 @@ window.addEventListener('DOMContentLoaded', scheduleImagingReload);
4: ('Apps installed', 'Type-specific scripts complete. Preparing for Intune enrollment.'), 4: ('Apps installed', 'Type-specific scripts complete. Preparing for Intune enrollment.'),
5: ('Enrolling in Intune', 'PPKG installing - device joining Azure AD + Intune. ~5-10 min, reboot to follow.'), 5: ('Enrolling in Intune', 'PPKG installing - device joining Azure AD + Intune. ~5-10 min, reboot to follow.'),
6: ('Waiting on first Intune sync','Post-PPKG settle (~120s). Triggering Schedule #3 sync repeatedly.'), 6: ('Waiting on first Intune sync','Post-PPKG settle (~120s). Triggering Schedule #3 sync repeatedly.'),
7: ('Awaiting Intune lockdown', 7: ('Registered - assign category',
'Device ID captured. If Device Category is NOT yet set in Intune, click "set category" first. Bay then waits for the Intune-driven LAPS-prompt reboot to apply the lockdown configuration.'), 'Phase 1 (Intune Registration) complete. Click "set category" in the Intune portal to drop the bay into the right config-profile group.'),
8: ('Imaging complete', 8: ('Imaging complete',
'Lockdown applied. Bay rebooted into ShopFloor session. Ready for production.') 'Lockdown applied. Bay rebooted into ShopFloor session. Ready for production.')
} %} } %}
@@ -63,6 +63,22 @@ window.addEventListener('DOMContentLoaded', scheduleImagingReload);
{% set is_done = s.status == 'succeeded' %} {% set is_done = s.status == 'succeeded' %}
{% set border = 'danger' if is_failed else ('success' if is_done else 'primary') %} {% set border = 'danger' if is_failed else ('success' if is_done else 'primary') %}
{% set friendly = stage_labels.get(stage_idx, ('Stage ' ~ stage_idx, '')) %} {% set friendly = stage_labels.get(stage_idx, ('Stage ' ~ stage_idx, '')) %}
{# Stage 7 fans out by sub-phase. Monitor pushes different stage #}
{# strings as it crosses each Phase 1-4 boundary. Swap friendly #}
{# label based on which keyword shows up. #}
{% if stage_idx == 7 and s.current_stage %}
{% set _cs = s.current_stage|lower %}
{% if 'ready for lockdown' in _cs or 'request lockdown' in _cs %}
{% set friendly = ('Ready - request lockdown',
'Phase 1-4 all complete (Registration, Device Config, Software Deploy, Credentials). Click "ARTS request" to initiate the lockdown workflow.') %}
{% elif 'credentials' in _cs or 'phase 4' in _cs %}
{% set friendly = ('Phase 3 / 4 - DSC + credentials',
'SFLD policy delivered, DSC pulling device-config.yaml + running per-app wrappers. SFLD share creds populating.') %}
{% elif 'sfld policy' in _cs or 'phase 2' in _cs or 'device configuration' in _cs %}
{% set friendly = ('Phase 2 - device configuration',
'Category was assigned in Intune. SFLD ConfigurationProfile (Function + SasToken) has delivered. DSC kicking off next.') %}
{% endif %}
{% endif %}
<details class="card border-{{ border }} mb-2 shadow-sm imaging-card" <details class="card border-{{ border }} mb-2 shadow-sm imaging-card"
data-serial="{{ s.serial }}" data-serial="{{ s.serial }}"
data-filter="{{ s.serial|lower }} {{ (s.hostname_target or '')|lower }} {{ (s.pctype or '')|lower }} {{ (s.machinenumber or '')|lower }} {{ (s.intune_device_id or '')|lower }} {{ friendly[0]|lower }} stage-{{ stage_idx }} {{ (s.status or 'in_progress')|lower }}"> data-filter="{{ s.serial|lower }} {{ (s.hostname_target or '')|lower }} {{ (s.pctype or '')|lower }} {{ (s.machinenumber or '')|lower }} {{ (s.intune_device_id or '')|lower }} {{ friendly[0]|lower }} stage-{{ stage_idx }} {{ (s.status or 'in_progress')|lower }}">