Files
shopdb-flask/plugins/endpoints/ADOPTION-TOOL-SPIKE.md
Cam Proudlock 6680c3c5de Merge the wilm delivery work into main
Ben Baker's installed-software collection, software delivery (run_script and
update_app), agentless adoption tool and command-queue hardening, with his
authorship preserved.

Reviewed before promotion. Fixed: the endpoints plugin tests were never collected
by pytest, the SBOM snapshot table's key would exhaust on MySQL, ingest did not
truncate two columns strict MySQL would reject, and update_app's version branch
pinned a digest for a file that route never serves. Agent packaging moved off
require_role('admin') onto a new endpoints.agentpackage permission.

Contract 0.27.0. Full suite 2231, frontend 314.
2026-08-30 19:41:15 -04:00

3.7 KiB

Adoption tool spike

Status: spike. Built on the origin/main baseline so it can be cherry-picked as a single unit once endpoint agent development is complete.

What it is

A one-shot, agentless enrollment tool. An admin generates a small download from the Endpoints key settings page; running the tool once on a PC creates a ShopDB PC (Computer) and Endpoint entry using only the endpoints collector key. It is NOT the endpoint agent: it installs nothing, runs no service, and sends no ongoing telemetry. It targets sites that want an inventory entry without running the full agent.

How it works

  1. Admin generates or reuses an endpoint agent key (existing /agentkey flow).
  2. Admin opens the "Adoption tool" section, confirms the base URL (prefilled from the browser origin) and pastes the collector key (prefilled when a key was just generated, since the secret is only shown once).
  3. POST /api/endpoints/adoptiontool/package (admin-gated) returns a ZIP with adopt.config.json, README.txt, and shopdb-adopt.exe when a prebuilt binary is staged on the server.
  4. On the target PC, shopdb-adopt.exe reads the config beside it (or CLI args), then POSTs to /api/collector/endpoints with X-API-Key and adopt=true. The existing _adopt_computer path creates the Computer + EndpointState.

Collection

The tool gathers the same identity, hardware, and SBOM subset the endpoint agent collects, using identical WMI queries and wire keys so the server stores it without translation:

  • Identity: hostname, loggedinuser, ipaddress.
  • Hardware: serialnumber (Win32_BIOS), vendorname / pctype / modelnumber (Win32_ComputerSystem), osname and lastboottime (Win32_OperatingSystem).
  • SBOM: applications = both Uninstall registry hives (64-bit + WOW6432Node), de-duped {displayname, displayversion, publisher}. The server logs this as an unpersisted key today (same as the agent) until the SBOM store lands.

The tool requires administrator rights (enforced by its app manifest requireAdministrator, with a runtime elevation guard) because the machine Uninstall hives and full WMI need elevation, or collection would be silently partial.

Cherry-pick boundary

The spike is deliberately isolated. Cherry-pick exactly:

  • agent/ShopDbAdoptionTool/ (new standalone tool project, incl. app.manifest)
  • agent/ShopDbEndpointAgent.slnx (one line adding the project)
  • plugins/endpoints/api/adoption.py (new module; attaches to endpoints_bp)
  • plugins/endpoints/api/__init__.py (one-line import to register the route)
  • plugins/endpoints/frontend/views/AgentKeySettings.vue (new UI section only)
  • plugins/endpoints/ADOPTION-TOOL-SPIKE.md (this file)

plugins/endpoints/api/routes.py is intentionally untouched so the delivery spike changes there do not tangle with this feature.

Prebuilt exe distribution

The api container has no .NET SDK, so the package embeds the exe only when a prebuilt copy is staged at instance/adoptiontool/shopdb-adopt.exe. Otherwise the ZIP ships the config plus README (build the exe out of band, same model as the endpoint agent installer bundle). Follow-up: a CI job that publishes shopdb-adopt.exe and stages it into the image or instance path.

Known follow-ups

  • Agentless health signal: an adopted PC never reports again, so EndpointState.lastreportedat reflects only the adoption moment. The fleet health/dashboard logic should distinguish "agentless, adopted" from "agent expected but silent" so these PCs do not read as permanently failed. Left out of this spike to keep the server create-path unchanged for a clean cherry-pick; the tool does not send an agentless marker yet because the server does not persist one (KNOWN_PAYLOAD_KEYS).
  • CI packaging of the prebuilt exe (see above).