main was 16 days and 259 commits behind the line the product is actually built on, at contract 0.30.0 against 0.35.0, with no per-PC credential code at all. It was neither current nor curated - just stale. This brings it forward and, at the same time, makes it mean something: main is what a receiving site installs, and nothing else. WHAT IT CARRIES. Twelve plugins - backups, computers, endpoints, guides, knowledgebase, machines, network, notifications, printers, slides, tools, warranty - plus applications, which is manifest-less core and always ships. The only manifest dependency inside that set is endpoints on computers, and both are in it, so the closure is self-contained. WHAT IT DOES NOT. employees, geenforce, measuringtools, printedparts and usb stay on the site line. So do the Windows installer tree, the VM rehearsal helpers, the agent tooling config, one site's data loader, the internal audit and findings records, and the planner spreadsheet. 1,135 tracked files against 1,438. A REMOVAL THAT BREAKS THE APP IS NOT A REMOVAL, and two nearly shipped: deploy/site-profile-universal.json still named all seventeen plugins. It is the file docs/DEPLOY.md tells a site to provision from, so a fresh install would have failed at `flask plugin apply-profile` with PluginError - the first thing a receiving site does, broken by the branch meant to serve them. It now names the twelve that exist, and its comment says the two must agree. agent/ was never refreshed. Whoever populated this branch copied shopdb/, plugins/, frontend/ and tests/ from the site line and left the agent tree at its September state: 22 C# and PowerShell sources missing, including AgentCredentials, EnrollmentService, AgentHttpFactory and the fleet-alert client, plus one file the site line had deleted still present. The old tree is internally consistent, so it compiles, and nothing in CI builds it - every gate was green over a server that speaks enrollment and per-PC credentials to a bundled agent source that cannot. Resynced whole. DECISIONS THIS ENCODES, rather than defers: - The plugin-authoring lab builds printedparts, whose manifest depends on employees, so it could not stay. The lab remains on the site line and main ships no build-along tutorial. That is a real loss for an adopting developer and is recorded here rather than discovered later. - Recognition, Training and Recertification notifications are no longer seeded. Each splits one notification into a card per employee and renders a photo, which needs a plugin this branch does not bundle. Seeding them would offer an author a type that cannot resolve anybody. A site that installs employees gets them from that plugin's own seed. - Windows/IIS is documented as the legacy path throughout, and the README leads with Docker, because that is what a receiving site gets. The API description is regenerated for THIS branch - 347 paths and 483 operations, down from 415 and 573 - so the published contract describes what is here rather than what the site line serves. docs/CONFIG.md lost the two measuring-tool label keys the code no longer declares, which two lanes had decided opposite ways. Suite: 3124 passed, 6 skipped. Naming and style gates pass. The docs gates run rather than skip, and every index line count is derived from the file it names.
8.8 KiB
Running the collector reporters on a fleet
Follow this to put PC reporting on a fleet that does not have it yet, or to move an existing fleet off a classic-ASP reporter. The payload contract is COLLECTOR-PAYLOADS and the credential choice is COLLECTOR-AUTH; you should not need either open to work through this page.
Adopting the whole tool set at a plant that has none of it is a wider job - ADOPTING-AT-ANOTHER-SITE.
1. Use the shipped reporters
Do not write your own. Two scripts ship in this repository and version with the contract they implement:
| Script | Reports | Posts to |
|---|---|---|
plugins/computers/client/Report-AssetToShopDB.ps1 |
hostname, BIOS serial, pc-type, logged-in user, make/model, OS, last boot, machine number, device id, every routable NIC | POST /api/collector/computers |
plugins/printers/client/Report-PrintersToShopDB.ps1 |
every real print queue on the host | POST /api/collector/printers |
Both run as SYSTEM, always exit 0 so "last run result" stays clean, and log to
C:\Logs\Shopfloor\. Neither names a site: ADR-015 makes a site name in product
code a defect, and these ship everywhere.
Each reads its configuration in this order:
- Its own parameters (
-ApiUrl,-ApiKey), which a scheduled task's arguments can supply for testing. HKLM:\SOFTWARE\GE\ShopDB-BaseUrlfor the server andCollectorKeyfor the shared key. This is the secret store every shipped reporter reads, and whatever images or configures the bay is what provisions it.
With neither, the script logs the reason and exits without posting.
Which credential it sends is decided on the PC, not in configuration: if the
PC holds a per-PC credential it is sent as X-Endpoint-Credential and the shared
key is not sent at all; otherwise the shared key goes as X-API-Key. If the
server refuses the credential as invalid or revoked, the reporter retries the
same POST once with the shared key, which is what makes a revoke a rollback
rather than an outage.
Shortcut for a single site: Settings > Computers > Asset reporter generates
Report-AssetToShopDB.ps1 with your server's URL already in the parameter
defaults, and shows its SHA-256. The key is deliberately not included.
2. Prepare the server
- Enable the
computersplugin (andprinters, if you want observed queues). - Mint the credential the fleet will start on - a managed token scoped to
collector.ingest. COLLECTOR-AUTH section 4 has the steps. An un-enrolled fleet needs this even if you intend to move to per-PC credentials, because enrollment itself auto-issues only to a call the shared key authenticated. - Set
collector_corporate_rangesto this site's routable CIDRs. Leave it blank and the server falls back to the NIC the bay says carries the default route, which is a guess on any bay with two NICs. - Map your imaging pc-types. Unmapped values only warn, but every report warns until you do.
3. Deliver the key to the PCs
HKLM:\SOFTWARE\GE\ShopDB value CollectorKey, ACL'd to SYSTEM and
Administrators. How it gets there depends on what you run - an imaging task,
Intune, DSC or by hand - and the options with their trade-offs are in
COLLECTOR-AUTH section 6.
Two rules regardless: never bake the key into a script that lives on a file share, and never put it in a manifest or a scheduled task's arguments.
4. Schedule the reporter
Reporting is an EVENT on a schedule, not a state to converge on. Two placements, pick one:
- As a scheduled task, registered at imaging time, by Intune, or by hand. SYSTEM, RunLevel Highest, at startup plus an interval.
- As an entry in whatever enforces configuration on your floor, run off a share every cycle with no local copy. Order the key-provisioning step BEFORE it so the key is present the same cycle the first report fires.
Either way, run it ALONGSIDE whatever reports today during rollout. Do not remove the old path until the new one is proven.
5. Stage the rollout
- Leave the existing reporting in place. Provision
CollectorKeyand enable the plugins. - Add the reporter on a handful of pilot bays, one per pc-type. It cannot break enforcement: it never throws and always exits 0.
- Verify on the server. Pilot PCs appear or update,
actioniscreated/updated, and every warning is understood - map any unmappedpctype, add missing OS strings to theoperatingsystemsvocabulary. Cross-check the client log'sOKlines against the audit log. - Roll it out fleet-wide. From the
commonscope, every pc-type gets it. - Once ShopDB is the system of record and has survived a full imaging cycle, retire the old reporter.
- Migrate to per-PC credentials, then switch the shared key off. That is its
own rollout and deliberately comes last: read
COLLECTOR-AUTH for what a PC does to enroll and what an
admin approves, and
plugins/endpoints/docs/PER-PC-CREDENTIALS-ROLLOUT.mdfor the order the shared key has to be cleared out of the places it lives. Both shipped reporters already send a credential when one is present and fall back to the shared key when it is not, so a PC that has not enrolled keeps reporting and nothing has to be redeployed to start.
6. Verify one PC
Invoke-RestMethod -Uri 'https://shopdb.example.net/api/computers/by-hostname/<HOSTNAME>'
The PC should exist with its serial, type and last-reported timestamp. The
client log is C:\Logs\Shopfloor\report-asset-YYYYMMDD.log (printer queues:
report-printers-YYYYMMDD.log); it records the POST line and the server's
response verbatim, including which credential it used.
7. When a bay does not report
| Symptom | HTTP | Cause / fix |
|---|---|---|
Invalid API key |
401 | The X-API-Key header is missing or wrong. Confirm the client key matches COLLECTOR_API_KEY_COMPUTERS (or the shared COLLECTOR_API_KEY) or is the managed token you minted. Check the client actually read it. The querystring form no longer works. |
Collector API key not configured |
500 | Fail-closed: no env key set server-side and the caller presented no managed token. A SERVER config gap, not a client problem. |
Endpoint credential is unknown or revoked |
401 | The PC's credential was revoked, or the database was restored past its issue. The reporter falls back to the shared key on its own; let the PC enroll again to restore it. |
The shared key is not accepted for this endpoint |
401 | This PC has enrolled, so it must use its own credential - or the shared key is switched off site-wide. Check that credential.bin is present and readable by SYSTEM. |
The request names a different endpoint than the credential |
403 | The hostname in the payload is on a different asset than the credential, or on no computer record at all. The message says which. Do not retry; fix the record. |
No collector registered for plugin computers |
404 | The plugin is disabled or not loaded on that instance. Enable it. |
hostname is required / No data provided |
400 | Empty body, non-JSON body, or missing identity field. Check -ContentType 'application/json'. |
Internal error processing collector payload |
500 | Generic by design - the server does not leak the cause. The real error is in the server log (Collector upsert failed for computers). |
queues is required; send an empty array for a host with no queues |
400 | The printers payload omitted queues entirely. Absent and empty are not the same thing here. |
| A bay's observed queues all vanished | 200 | It reported queues: [], which legitimately clears the host. Check the client log for posting NOTHING (a failed enumeration correctly sends nothing) versus an empty set. If the bay really has queues, fix the enumeration on that host. |
Observed queues show as unknown |
200 | The queue matched no printer asset by port address or name. Add the printer to ShopDB with its IP and re-read - matching happens at read time, so the bay does not need to report again. |
warnings present but action is created/updated |
200 | Soft issues only; the row WAS written. Common: unmapped pctype, unknown osname, unknown app name, pcsubtype not stored. No action needed unless the warning matters to you. |
| The wrong IP is recorded as primary | 200 | collector_corporate_ranges is blank or does not cover this bay. The bay reports every NIC and takes no view; set the ranges. |
Client-side logs are under C:\Logs\Shopfloor\. Server-side, the Flask app log
carries upsert failures and per-plugin schema failures.