From 10ed83e14cab863a3e69d621c87f866b72c536e8 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 26 Jun 2026 21:35:23 -0400 Subject: [PATCH] Collector: ingest GE-Enforce/enrollment data with configurable pc-type mapping Extends the computers collector so it can replace the classic api.asp updateCompleteAsset path that the shopfloor PC fleet uses to auto-update data. Collector schema (project naming) now accepts the GE-Enforce/enrollment shape: machinenumber, pctype, pcsubtype, serialnumber, loggedinuser, lastboottime, lastcheckin, ipaddress, vendorname, modelnumber, osname, installedsoftware. - machinenumber -> Asset.assetnumber (skips the 9999 imaging placeholder, falls back to hostname), on create and update. - pctype -> ComputerType via a configurable mapping (see below). - vendor/model created if missing (free vocab); OS looked up (controlled, warns if unknown); pcsubtype accepted but not yet stored (warning). - Dropped per scope: VNC/WinRM flags, warranty, DNC config, multi-NIC. Configurable pc-type mapping (the gea-shopfloor-* imaging taxonomy -> ComputerType): defaults + resolution live in plugins/computers/pctypemap.py (plugin domain, contract-pure - reads Setting via shopdb.api); overrides stored as pctypemap_ settings, seeded on plugin install, edited in Settings > System > "Collector PC Type Mapping" (new UI section). Migration doc: docs/COLLECTOR-INTEGRATION.md maps classic api.asp fields + GE-Enforce status fields to the collector schema, documents machine-number sourcing (registry MachineNo first, then C:\Enrollment\machine-number.txt) and that the transport is interim. Tests: complete-asset payload maps machinenumber/pctype/vendor/model/os; 9999 placeholder falls back to hostname. 186 tests pass, naming green, app boots, mapping UI verified. Co-Authored-By: Claude Opus 4.8 --- docs/COLLECTOR-INTEGRATION.md | 74 +++++++++++++++ .../src/views/settings/SystemSettings.vue | 75 ++++++++++++++- plugins/computers/pctypemap.py | 46 +++++++++ plugins/computers/plugin.py | 93 +++++++++++++++++-- shopdb/core/api/settings.py | 3 +- tests/test_core/test_collector_contract.py | 50 ++++++++++ 6 files changed, 332 insertions(+), 9 deletions(-) create mode 100644 docs/COLLECTOR-INTEGRATION.md create mode 100644 plugins/computers/pctypemap.py diff --git a/docs/COLLECTOR-INTEGRATION.md b/docs/COLLECTOR-INTEGRATION.md new file mode 100644 index 0000000..6edb752 --- /dev/null +++ b/docs/COLLECTOR-INTEGRATION.md @@ -0,0 +1,74 @@ +# Collector integration (PC auto-update) + +How the shopfloor PC fleet pushes inventory into shopdb-flask, replacing the +classic ASP `api.asp?action=updateCompleteAsset` path. + +## Endpoint + +`POST /api/collector/computers` + +Auth: API key header `X-API-Key: `, resolved as `COLLECTOR_API_KEY_COMPUTERS` +then the shared `COLLECTOR_API_KEY` (ADR-006). Idempotent upsert keyed on +`hostname`. + +## Payload (project naming convention: lowercase concatenated) + +| Field | Meaning | Flask target | +|-------|---------|--------------| +| `hostname` (required) | identity | `Computer.hostname` | +| `machinenumber` | machine number | `Asset.assetnumber` (skips `9999` placeholder, falls back to hostname) | +| `pctype` | imaging pc-type | `Computer.computertypeid` via the configurable mapping | +| `pcsubtype` | finer class | accepted, not yet stored (warning) | +| `serialnumber` | BIOS serial | `Asset.serialnumber` | +| `loggedinuser` | current user | `Computer.loggedinuser` | +| `lastboottime` | ISO datetime | `Computer.lastboottime` | +| `lastcheckin` | ISO datetime | accepted (heartbeat) | +| `ipaddress` | primary IP | primary `Communication` | +| `vendorname` | manufacturer | `Computer.vendorid` (created if missing) | +| `modelnumber` | model | `Computer.modelnumberid` (created if missing) | +| `osname` | OS caption | `Computer.osid` (looked up; warned if unknown) | +| `installedsoftware` | `[{name, version}]` | `ComputerInstalledApp` (known apps only) | + +Response: `{status, action: created|updated, assetid, identityvalue, warnings[]}`. + +## Source of truth on the PC (current method, may change) + +The data already exists at image time and at runtime: + +- **machine number**: registry `HKLM\SOFTWARE\[WOW6432Node\]GE Aircraft Engines\Dnc\General\MachineNo` + FIRST (authoritative post Update-MachineNumber; ignore the `9999` placeholder), + then `C:\Enrollment\machine-number.txt` as fallback. This is exactly what + GE-Enforce.ps1 already does. +- **pc-type / pc-subtype**: `C:\Enrollment\pc-type.txt` / `pc-subtype.txt` + (the `gea-shopfloor-*` taxonomy). +- **serial / vendor / model / os / user / boot**: live WMI on the PC. + +GE-Enforce currently writes a status JSON to the SFLD share rather than POSTing. +Whatever transport is used (a relay reading those status files, or a direct POST +later), map its field names to the table above. + +## pc-type mapping (configurable) + +`pctype` (e.g. `gea-shopfloor-cmm`) is mapped to a flask Computer Type through +`pctypemap_` settings (Settings > System > "Collector PC Type Mapping"). +Defaults live in `plugins/computers/pctypemap.py` and are seeded on plugin +install; edit per site in the UI. Unmapped pc-types are recorded as a warning, +not an error. + +## Classic api.asp field mapping (for migrating the PowerShell scripts) + +| Classic `updateCompleteAsset` form field | Collector field | +|---|---| +| `hostname` | `hostname` | +| `machineNo` | `machinenumber` | +| `pcType` | `pctype` | +| `serialNumber` | `serialnumber` | +| `loggedInUser` | `loggedinuser` | +| `lastBootUpTime` / `lastBootTime` | `lastboottime` | +| `manufacturer` | `vendorname` | +| `model` | `modelnumber` | +| `osVersion` | `osname` | +| `installedApps` | `installedsoftware` | + +Not carried over (no current home): warranty fields, DNC config, multi-NIC +detail beyond the primary IP, VNC/WinRM flags. diff --git a/frontend/src/views/settings/SystemSettings.vue b/frontend/src/views/settings/SystemSettings.vue index ff18a5f..c3fc4e5 100644 --- a/frontend/src/views/settings/SystemSettings.vue +++ b/frontend/src/views/settings/SystemSettings.vue @@ -440,6 +440,41 @@ + + +
+

Collector PC Type Mapping

+ +
+

+ When the collector ingests a PC, its imaging pc-type (from + C:\Enrollment\pc-type.txt) is mapped to one of your Computer Types. + Adjust the mapping per site. +

+ +
+ + + + + + + + + + +
Imaging pc-typeComputer Type
{{ row.pxetype }} + +
+
+
+
{{ error }}
@@ -448,7 +483,7 @@