The scanner has been reporting the same count for weeks, which is what a rule that only prints becomes. It now FAILS the build, and it looks where the leaks actually were: PowerShell, the installer, the seeds, generated JSON, the frontend - case-insensitively, across plugins, shopdb, scripts, deploy, tools. A line that is deliberate declares itself with an ADR-015-OK marker and a reason, so the claim is visible in review instead of tolerated in silence. What it found, fixed here: - The shadow client wrote one site's ShopDB URL into HKLM whenever the registry disagreed. At the site it was written for that reads as healing drift; anywhere else it overwrites the site's own address on every enforce cycle, and the site cannot win because the cycle repeats. The bay's value now wins, an explicit -BaseUrl seeds it, and with neither there is nothing honest to write, so it says so and skips. - The kiosk dispatcher fell back to one plant's host when HKLM was unset, so a kiosk elsewhere quietly opened a server it has no business reaching. The fallback is now this site's site_base_url, baked in at seed time, and the dispatcher refuses rather than guessing when neither is set. Its legacy shortcut matcher derives the host from that URL instead of naming one. - The OpenAPI generator hardcoded a production hostname into every spec it generated, which then published to a public wiki. The relative mount is the only server it can honestly name; a site passes its own by environment. - Placeholders and examples in the UI and the client help offered real internal subnets and a real production URL. They now use documentation ranges. Both publication gates - the export scrub and the docs publishability test - carry the site patterns, which neither did. One plant's hostname, FQDN and internal networks are out of the documentation and the generated specs. Comments naming the reference site are reworded rather than deleted: the reasoning is worth keeping, the plant name is not what makes it true.
95 lines
5.2 KiB
Plaintext
95 lines
5.2 KiB
Plaintext
# ShopDB Flask API - LLM guide
|
|
|
|
ShopDB is a plugin-based asset-management system (PCs, printers, machines,
|
|
network devices, measuring tools, applications, knowledge base, USB, warranties)
|
|
for GE Aerospace sites. This file is the quick entrypoint; the full machine
|
|
spec is the OpenAPI at `/api/docs/openapi.json` (browse it at `/api/docs`).
|
|
|
|
## Installing and operating this server (read this before answering "how do I install/fix it")
|
|
The people running these servers are often not Windows, IIS or Python
|
|
specialists, and they ask assistants for help. Two documents are authoritative:
|
|
- `docs/INSTALL-WINDOWS.md` - installing a NEW site. One offline installer `.exe`.
|
|
- `docs/OPERATE-WINDOWS.md` - restart, logs, backups, upgrades, troubleshooting.
|
|
Both ship in `docs/` inside the install directory on every installed server.
|
|
|
|
Do NOT walk someone through `docs/INSTALL-WINDOWS-IIS.md` or
|
|
`docs/DEPLOY-WINDOWS-IIS.md` for a new site. Those are the MANUAL procedure, kept
|
|
only for hand-built servers that predate the installer; following them produces a
|
|
server the installer then refuses to upgrade.
|
|
|
|
Day-2 operations all go through `shopdb-admin.ps1` in the install directory
|
|
(default `C:\shopdb-flask`): `status`, `restart`, `logs`, `check`, `verify`,
|
|
`backup`, `plugins`, `open`. Before diagnosing anything, ask for the output of
|
|
`shopdb-admin.ps1 check -Json` - it reports version, publishing method, IIS and
|
|
pool state, HTTP reachability, database host and reachability, Python version,
|
|
installed plugins and errors, and it contains no secrets. `verify -Path <name>`
|
|
answers "does this server carry component X" from the on-box CycloneDX SBOM.
|
|
|
|
Python is 3.14 and the wheelhouse is locked to it; an upgrade against a venv
|
|
built by a different minor version is refused by design.
|
|
|
|
## Bulk-loading a site's data
|
|
Two routes, and the right answer depends on what the site has:
|
|
- SPREADSHEET, no developer (the common case): `flask csv templates --out <dir>`
|
|
generates templates FROM THE LIVE SCHEMA, then `flask csv import --dir <dir>`
|
|
checks and `--commit` applies. Foreign keys accept the NAME of the referenced
|
|
row ('Bay 3'), not a numeric id, and resolve across files in one run. Dry run
|
|
is the default; nothing is written unless every row passes; re-importing an
|
|
edited file updates rather than duplicates. See `docs/CSV-IMPORT.md`.
|
|
- A SOURCE DATABASE to script against: the HTTP import API, `docs/IMPORT-API.md`
|
|
and `docs/IMPORT-ADOPTION.md`.
|
|
Do NOT hand-write CSV templates - generate them. User accounts are deliberately
|
|
not CSV-importable.
|
|
|
|
## Base URL
|
|
Prod (West Jefferson): `https://shopdb.example.net/shopdb`
|
|
All API paths are under `/api` (e.g. `<base>/api/assets`). Dev: `http://localhost:5001`.
|
|
|
|
## Auth
|
|
Three schemes:
|
|
- **Bearer JWT** - most endpoints. Get one by logging in, or use a managed
|
|
Personal Access Token (PAT). Send `Authorization: Bearer <token>`.
|
|
- Login: `POST /api/auth/login` `{ "username": "...", "password": "..." }`
|
|
-> `data.access_token`. Refresh: `POST /api/auth/refresh`.
|
|
- PATs are minted in the UI (Settings > API Tokens); a *scoped* PAT is limited
|
|
to named permissions and suspends the admin bypass.
|
|
- **X-API-Key** - unattended/service endpoints (collector ingest, GE-Enforce
|
|
fetch). Send `X-API-Key: <managed-token>`.
|
|
- **Public** - some read endpoints (e.g. printer install-list, employee search,
|
|
dashboards) need no auth.
|
|
|
|
Auth level per endpoint is in the OpenAPI `security` field: `bearerAuth`,
|
|
`apiKeyAuth`, or none. Admin-only and permission-gated routes both use bearer.
|
|
|
|
## Response envelope
|
|
JSON endpoints return `{ "status": "success", "data": <payload>, "meta": {...} }`.
|
|
Errors: `{ "status": "error", "message": "...", "code": "..." }` with an HTTP 4xx/5xx.
|
|
Lists include `meta.total` / pagination. A few feed endpoints (screensaver, some
|
|
installer text formats) return raw text/JSON without the envelope - noted per route.
|
|
|
|
## Common recipes
|
|
- Search everything: `GET /api/search?q=<term>` (multi-word = AND across words).
|
|
- List assets on the map: `GET /api/assets/map`.
|
|
- List a type: `GET /api/printers`, `/api/computers`, `/api/machines`,
|
|
`/api/network`, `/api/measuringtools` (paginated: `?page=&perpage=`).
|
|
- Get one: `GET /api/printers/<id>` etc.
|
|
- Create (bearer): `POST /api/printers` `{assetnumber, windowsname, vendorid, ...}`.
|
|
- Reports: `GET /api/reports` (list), `GET /api/reports/pc-relationships` (PC<->machine).
|
|
- Printer installer data: `GET /api/printers/install-list` (public; add
|
|
`?format=text` for a pipe-delimited variant); `GET /api/printers/pc-default?machine=<n>`.
|
|
- Collector ingest (X-API-Key): `POST /api/collector/computers`.
|
|
- GE-Enforce: `GET /api/geenforce/manifest?pctype=<scope>`,
|
|
`GET /api/geenforce/payload/<sha256>`, `POST /api/geenforce/report`.
|
|
- Import (admin PAT, preserves timestamps with `X-Import-Mode`): see docs/IMPORT-API.md.
|
|
|
|
## Conventions
|
|
- DB-mirrored params/fields use lowercase concatenated names (no underscores):
|
|
`locationid`, `vendorid`, `windowsname` - match them exactly.
|
|
- IDs in paths are integers.
|
|
- Plugin endpoints live under the plugin's prefix (`/api/<plugin>/...`).
|
|
|
|
## Full reference
|
|
- Machine spec: `GET /api/docs/openapi.json` (OpenAPI 3.1, 362 operations).
|
|
- Interactive: `GET /api/docs` (Redoc).
|
|
- Human reference: `docs/API-REFERENCE.md`.
|