Commit Graph

10 Commits

Author SHA1 Message Date
cproudlock
86fbc132dd GE-Enforce: backfill Keyence pc-subtype.txt from installed ProductCode
Pre-2026-05 Keyence images didn't write pc-subtype.txt via startnet.cmd. Without
a subtype the share manifest's per-model PCTypes gate falls back to the default
(VR-6000), causing the wrong model to install on VR-3000 / VR-5000 boxes.
Detect the installed VR-3000/5000/6000 by its uninstall ProductCode and
persist the subtype so subsequent GE-Enforce cycles + the share manifest gate
route correctly.
2026-05-24 07:03:54 -04:00
cproudlock
72e4058d89 GE-Enforce: bump enforcerVersion '2.5' -> '2.5.1' so convergence-check shows the remount fix landed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 19:08:27 -04:00
cproudlock
c8ef05b869 GE-Enforce: re-mount W: before status write + null guards
Root cause of fleet not reporting: long-running entries (UDC's
WaitTimeoutSec=120) keep the dispatcher CPU-busy with no SMB traffic
to W:. SMB server times out the idle session. W: stays as a "mapped"
drive letter on the client but Path operations against it fail with
weird errors (e.g. "Cannot bind argument to parameter 'Path' because
it is null" via downstream Join-Path / Test-Path null cascades).

Fix:
- Re-attach W: at the top of the status write-back block (cheap; if
  still alive net use returns 'already mapped'; if dead, freshly
  remounts).
- Null-guard $hostname (fall back to 'UNKNOWN') and explicitly throw
  if $driveLetter is unset (catch surfaces a clear error in log).
- Pair with UDC manifest WaitTimeoutSec reduction 120 -> 60 on the v2
  share to limit how long the SMB stays idle in the first place.

Surfaced via blah*.txt log captures from 3 deployed bays (3105, 3115,
3116, 3118 era) - all showed "Status write-back failed: Cannot bind
argument to parameter 'Path' because it is null" while everything
upstream (manifest entries) ran clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 19:02:16 -04:00
cproudlock
707a0f94c2 GE-Enforce: prefer DNC reg MachineNo over machine-number.txt
machine-number.txt holds the imaging-time MN. PCs imaged with
placeholder 9999 (tech intends to flip via Set-MachineNumber later)
keep 9999 in that file even after Update-MachineNumber writes the
real MN to HKLM:\...\Dnc\General\MachineNo. Status.json was reporting
9999 across the fleet because of this.

Now reads DNC reg first; only falls back to machine-number.txt if reg
is missing or also 9999. Existing convergence-check.txt unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 17:12:55 -04:00
cproudlock
9b2ee11840 GE-Enforce: write machineNumber + bump enforcerVersion to 2.5
Adds machineNumber field to status.json (read from C:\Enrollment\machine-number.txt).
Bumps enforcerVersion to '2.5' so check-fleet-convergence.txt's column
flips when fleet picks up the self-update. Pairs with the Install-FromManifest
v2.5 (WaitTimeoutSec) so both bumps land together.

Convergence-check txt updated to display the new MN column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 16:55:29 -04:00
cproudlock
3cb79715bf GE-Enforce: bump enforcerVersion to 2.4 in status.json write-back
Hardcoded version string surfaced in _outputs/logs/<host>/status.json
that the fleet check-in dashboard reads. Bump aligned with
Install-FromManifest lib v2.4 (PCTypes alias map + network-share EXE
staging). Lets the convergence-check oneliner distinguish PCs that
have picked up the post-rename dispatcher from those still on 2.0.

When pushed to share + the self-update common/manifest.json entry's
DetectionValue is bumped to the new SHA256 (commit notes record the
hash but the manifest itself lives on the v2 share, not in this repo
by design), every fleet PC's next cycle re-fires the self-update,
copies new bytes locally, the cycle after that writes status.json
with enforcerVersion=2.4. Fully visible in the dashboard read.

new GE-Enforce.ps1 SHA256:
  C8C14CFCE539ACDC6D16B31D2C456A5239516BDFA1EBFC820794A2D58BA7D9AC

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:39:40 -04:00
cproudlock
285d81edc4 GE-Enforce: alias-aware manifest dir resolution
Phase 2 of the gea-shopfloor-* rename. Pairs with the v2 share manifest
dir renames done in /home/camp/pxe-images/tsgwp00525-v2/ this session
(local-only, syncs to prod separately):

  standard-machine    -> gea-shopfloor-collections
  cmm                 -> gea-shopfloor-cmm
  keyence             -> gea-shopfloor-keyence
  genspect            -> gea-shopfloor-genspect
  waxandtrace         -> gea-shopfloor-waxtrace
  display             -> gea-shopfloor-display
  lab                 -> merged into gea-shopfloor-common
  (new)               -> gea-shopfloor-nocollections (clone of collections w/o UDC)
  (new)               -> gea-shopfloor-heattreat (placeholder)
  (new)               -> gea-shopfloor-common (Timeclock + Lab merge)

GE-Enforce now walks an alias group when the constructed dir name has
no manifest.json. Fleet PCs whose pc-type.txt still says "Standard" /
sub "Machine" continue to find their manifest at the new
gea-shopfloor-collections location, so the rename is invisible to them.
After Phase 4 (startnet.cmd) lands and freshly-imaged PCs write the new
strings directly, the alias resolution still works for both forms.

Smoke-tested on win11 VM as SYSTEM via qga: legacy Standard/Machine
and new gea-shopfloor-collections both reach the same manifest, fire
the same entries, complete cleanly.

Phases 3+4 (repo folder renames + startnet.cmd menu) deferred per
project-shopfloor-rename-reorg memory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 07:27:29 -04:00
cproudlock
c2fef53543 GE-Enforce: prune *.log older than 30 days each cycle
Bounds growth of C:\Logs\Shopfloor (per-day enforce-YYYYMMDD.log files),
C:\Logs\SFLD (Start-Transcript -Append accumulates), and C:\Logs\Keyence.
Today's enforce log is never touched (LastWriteTime = now). Cheap flat
scan per cycle; logs only when something actually got pruned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:57:23 -04:00
cproudlock
1886857c0f Use [Environment]::MachineName instead of $env:COMPUTERNAME
Live kernel NetBIOS name instead of the PowerShell process-env cache.

$env:COMPUTERNAME is populated when PowerShell starts and does not
update if the PC gets renamed (common on Intune-managed Autopilot /
AADJ devices that come up with a DESKTOP-XXXXXXXX name and get
renamed by policy post-imaging). Until the next reboot, the env var
stays stale while 'hostname.exe' already reports the new name.

That mismatch showed up live on the first production retrofit: the
status.json was written under _outputs/logs/DESKTOP-XXXXXXXX/
instead of under the device's current name, and the
TargetHostnames filter and monitor drift-check would likewise see
the stale name.

[Environment]::MachineName reads from the kernel on each call, so
it always returns the current NetBIOS name. Swapped at all five
callsites in GE-Enforce.ps1, Register-GEEnforce.ps1, and
Install-FromManifest.ps1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:51:05 -04:00
cproudlock
eb68793e79 Stage 2a: unified GE-Enforce framework + share-root mirror
Consolidates per-type enforcers (CMM, Keyence, Machine, Common, Acrobat)
into one dispatcher driven by pc-type.txt + site-config and a share-side
manifest layout. Same share is now the single source of truth for routine
software updates without re-imaging.

Runtime:
  common/GE-Enforce.ps1           SYSTEM scheduled task. Reads
                                   common/manifest.json plus optional
                                   <pcType>/manifest.json and
                                   <pcType-subType>/manifest.json.
                                   Dispatches each entry through the lib.
                                   Writes _outputs/logs/<hostname>/status.json
                                   on the share after each cycle for fleet
                                   monitoring.
  common/Register-GEEnforce.ps1   Task registration. Triggers: AtLogOn +
                                   every 5 min (jittered per-PC from
                                   hostname hash) + daily at 05:45,
                                   13:45, 21:45 EST shift windows.
                                   Unregisters legacy per-type tasks on
                                   install so the two coexist at most for
                                   the duration of a single enforce cycle.
  common/Deploy-GEEnforce.ps1     Retrofit helper for already-imaged PCs
                                   (admin-run; copies runtime + registers
                                   task + optional immediate trigger).

Library (common/lib/Install-FromManifest.ps1):
  - New Type values: PS1, BAT, File, Registry, INF
  - New DetectionMethod values: Always, MarkerFile, ValueMatches, pnputil
  - TargetHostnames filter (exact + -like wildcards, ANDed with PCTypes)
  - Schema version check (logs WARN on manifest newer than lib MAJOR)
  - Auto-writes MarkerFile on successful one-shot PS1/BAT/CMD runs
  - MSI log scan on failure surfaces meaningful install errors
  - Lib version bumped 2.0 -> 2.1 for TargetHostnames

Observability:
  common/monitor-fleet-status.py  Scans _outputs/logs/*/status.json for
                                   stale check-ins, failed scopes, and
                                   version drift. Respects scope (dir-name),
                                   PCTypes, and TargetHostnames filters so
                                   entries excluded from a PC do not
                                   false-flag as drift.

Regression harness:
  common/test/                    Parameterized VM harness + README
                                   covering every action type plus
                                   rollback, bad/missing SFLD creds, and
                                   schema versioning.

Imaging integration:
  Run-ShopfloorSetup.ps1 now stages GE-Enforce.ps1 and lib to
  C:\Program Files\GE\Shopfloor\ and invokes Register-GEEnforce.ps1
  at the end of setup. Legacy Register-CommonEnforce invocation is
  kept for the transition; it and the legacy per-type enforcer files
  are dead code once Register-GEEnforce runs and will be removed in a
  dedicated cleanup pass.

Standard-Machine manifest:
  eDNC entry bumped 6.4.3 -> 6.4.5. DetectionValue pinned to the
  4-part FileVersion 6.4.5.0 verified against a fresh install in the
  Win11 analyzer VM. UDC DetectionValue pinned to 1.0.34 (registry
  stores 3-part for UDC; verified live).

scripts/mirror-from-gold.sh:
  Restructured around share-root rsyncs (one pass per Samba share)
  to close gaps in the prior per-subdir layout: winpeapps/_shared/
  Applications (7.5 GB of Adobe + fonts + Java + Office + OpenText
  + printdrivers + wireless + Zscaler), additional winpeapps image
  types, and enrollment flat-layout root files. Adds
  --skip-clonezilla and --skip-reports.

Verified end-to-end in the Win11 analyzer VM:
  - Every action Type and DetectionMethod round-tripped
  - PCTypes filter (Oracle excluded on Shopfloor, Firefox included
    on Shopfloor and DESKTOP-*, excluded elsewhere)
  - TargetHostnames filter (exact, wildcard, no-match)
  - Upgrade path: XML hash bump + fleet re-copy
  - Rollback path: history-archive restore propagates via enforcer,
    fleet converges back without per-PC intervention
  - Status writeback + monitor script drift detection
  - Graceful degradation on bad creds, missing creds, share
    unreachable (all exit 0, log clearly, retry next cycle)

Not in this commit (follow-ups):
  - Retire legacy per-type *-Enforce.ps1 files and simplify
    09-Setup-*.ps1 scripts (coordinated multi-file cleanup)
  - Stage 2b: InUseCheck close-and-reopen, ApplyMode gating,
    UpdateWindow, .apply-now.txt sentinel, BITS pre-staging,
    1618 mutex retry, PostInstallCheck, Uninstall action
  - Management app (manifest CRUD + deploy + rollback + fleet view)
  - ShopFloor autologon persistence bug (deferred for next imaging
    attempt with live registry evidence)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:19:23 -04:00