Make the app distributable to other GE Aerospace sites (one self-hosted
instance per site, ADR-004). GE values remain the shipped defaults; every
site-specific behavior is now a Setting an admin can change in the UI.
Settings-driven site config:
- Branding: site/QR/badge logos, favicon, primary color (upload endpoints
mirror the map-blueprint pattern; new Settings > Branding section).
- ServiceNow: search/incident/change URL templates ({ticket}), ticket
prefixes, enable toggle. Defaults point at the current
geaerospaceqa.service-now.com global search. Disabled = plain-text tickets.
- Employee-id regex (employeeid_pattern), printer hostname template,
QR label targets (qr_target_printer / qr_target_usb, blank = asset page,
else URL template with placeholders), usb_label_style (barcode|qr).
- West Jefferson floor-plan PNGs removed from the tree; generic placeholder
ships as the map default and sites upload their own blueprint.
Security closeout:
- dashboarddefaults writes now require admin.
- Collector: generic error messages (no str(exc) leak); API key accepted
via X-API-Key header only (BREAKING: querystring api_key removed).
- IP-based login rate limiting (AUTH_RATELIMIT_* knobs) atop account lockout.
- Setting.set() creation race fixed (IntegrityError retry).
Release engineering and docs:
- __version__ 0.5.0 (distinct from __contract_version__, ADR-007),
CHANGELOG.md, Gitea Actions CI config, frontend version aligned.
- One wizard-first install story across README/DEPLOY; new CONFIG.md,
UPGRADE.md, BACKUP-RESTORE.md; CLAUDE.md and ROADMAP de-staled.
- Dockerfile multi-stage build now bundles the frontend; compose binds
MySQL to 127.0.0.1; stale database/schema.sql and one-off SQL removed.
Debt and fixes:
- .query.get() -> db.session.get() sweep; datetime.utcnow() removed
(naive-UTC via timezone-aware now); users.py on authz decorators.
- Fixed 4 stale tests (slides feed shape, shopfloor splitperemployee,
plugin contract purity) and the USB label page field mapping (both usb
modes emit the cmmc shape: device_id/device_desc).
- Health endpoint reports the real version.
248 tests pass; naming/style check green; frontend builds; fresh-DB
flask db upgrade + seeds verified; QR targets verified by decoding
rendered codes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
81 lines
3.6 KiB
Markdown
81 lines
3.6 KiB
Markdown
# 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: <key>`, resolved as `COLLECTOR_API_KEY_COMPUTERS`
|
|
then the shared `COLLECTOR_API_KEY` (ADR-006). Idempotent upsert keyed on
|
|
`hostname`.
|
|
|
|
> **Breaking change:** the API key must be sent in the `X-API-Key` header. The
|
|
> old `?api_key=<key>` querystring fallback has been removed, on every collector
|
|
> endpoint (`/api/collector/<plugin>`, `/pc`, `/apps`, `/heartbeat`, `/bulk`,
|
|
> `/status`). Querystring keys leak into access logs and proxy history. Update
|
|
> any caller still passing `api_key` in the URL to use the header instead.
|
|
|
|
## 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_<pxetype>` 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.
|