Nine documents carried a hand-typed contract version and every one was stale. One was load-bearing: PLUGIN-EXTERNAL-REPO.md told an external author to pin ">=0.13.0,<0.14.0" while the contract is at 0.19.0, so a plugin built by following that guide is refused by the loader at startup. The plugin count was wrong in six more. They now point at docs/PROJECT-MAP.md, which is generated. A test enforces it: no document may declare a version literal, a stated current version must match the code, and a stated plugin count must match the tree. ADRs are exempt from the current-version rule, because an ADR states the version a decision was taken AT - that is a record of the past, and rewriting it would falsify the record ADRs exist to keep. CONTRACT-STABILITY.md was missing 0.17.0, 0.18.0 and 0.19.0 - including the only BREAKING change in the series - in the one document a site reads to choose its pin. All three are recorded, with 0.19.0 called out: it took something away, and it shipped before it was written down, which is the argument for pinning tight rather than trusting that a minor bump is safe.
148 lines
9.5 KiB
Markdown
148 lines
9.5 KiB
Markdown
# API reference (index)
|
|
|
|
This page is an index and a pointer, not a full specification. It answers three
|
|
questions: what endpoints exist, who calls them, and what auth they require. The
|
|
detailed request and response shapes live in the live generated docs and in the
|
|
per-surface contract docs linked from each table below.
|
|
|
|
## Live and generated docs
|
|
|
|
The repo ships hosted, generated API docs. Start there:
|
|
|
|
- **Interactive spec:** `GET /api/docs` - a self-hosted Redoc page over the
|
|
generated OpenAPI spec. The Redoc bundle is vendored under
|
|
`shopdb/core/api/staticdocs/`, so it renders fully offline on the air-gapped
|
|
prod box (no CDN).
|
|
- **Raw spec:** `GET /api/docs/openapi.json` - OpenAPI 3.1, roughly 238 paths and
|
|
362 operations. Generated by `scripts/gen_openapi.py` from
|
|
`docs/api-inventory.json`; regenerate after any API change.
|
|
- **LLM / agent entry point:** `GET /api/docs/llms.txt` - a concise API guide
|
|
following the llms.txt convention, plus a read-only MCP server
|
|
(`mcp/shopdb_mcp.py`, built with `FastMCP.from_openapi` over the same spec).
|
|
The MCP server exposes a curated set of GET endpoints as tools for an agent to
|
|
query the asset database over HTTPS with a scoped read token; it never runs on
|
|
the prod box. Set it up on a work PC with
|
|
`<imaging-share>/github/setup-mcp.cmd`.
|
|
|
|
The docs blueprint is `shopdb/core/api/docs.py` (a core blueprint, always
|
|
mounted regardless of which plugins are staged into a site build).
|
|
|
|
Contract docs (linked per table below) hold the deep semantics: field mappings,
|
|
idempotency rules, rotation, error envelopes, staged rollout. This page only
|
|
routes you to the right one.
|
|
|
|
---
|
|
|
|
## 1. Fleet and client contracts (unauthenticated or token)
|
|
|
|
These are the endpoints the shopfloor PC fleet, kiosks, displays, and printer
|
|
installers call. They are consumed by machines, not by the interactive UI, and
|
|
they authenticate with a scoped service token or nothing at all.
|
|
|
|
| Endpoint | Auth | Purpose | Contract doc |
|
|
|---|---|---|---|
|
|
| `GET /api/geenforce/manifest?pctype=<scope>` | `geenforce.fetch` service token (`X-API-Key` or Bearer PAT) | Serve the current published manifest for a PC-type scope. ETag / 304 supported. | GE-ENFORCE-CLIENT.md, geenforce-api-cutover.md |
|
|
| `GET /api/geenforce/payload/<sha256>` | `geenforce.fetch` service token | Serve a payload blob (installer) by content hash so share-less PCs pull over HTTPS instead of SMB. Rate limited and size capped; the sha256 is the integrity guarantee. | GE-ENFORCE-CLIENT.md, geenforce-api-cutover.md |
|
|
| `POST /api/geenforce/report` | `geenforce.report` service token | Record one PC's enforcement cycle: applied manifest version plus per-entry self-heal outcomes. | GE-ENFORCE-CLIENT.md, geenforce-api-cutover.md |
|
|
| `POST /api/collector/<plugin>` | `X-API-Key` env key or a `collector.ingest` managed token | Generic idempotent inventory upsert; the PC fleet targets `/api/collector/computers`. | COLLECTOR-INTEGRATION.md |
|
|
| `POST /api/collector/pc`, `/apps`, `/heartbeat`, `/bulk` | `X-API-Key` or `collector.ingest` token | Legacy computers-only collector paths (predate ADR-006); deprecated in favor of `/api/collector/computers`. | COLLECTOR-INTEGRATION.md |
|
|
| `GET /api/collector/status` | `X-API-Key` or `collector.ingest` token | Collector liveness and endpoint list. | COLLECTOR-INTEGRATION.md |
|
|
| `GET /api/printers/install-list` | optional JWT (anonymous fleet or logged-in browser) | Flat list of network printers with floor-map positions for the signed installer. `?format=text` returns a pipe-delimited variant. | PRINTER-INSTALLER.md |
|
|
| `GET /api/printers/pc-default?machine=NNNN` | optional JWT | The PC's default printer by machine (asset) number, via the `defaultprinter` relationship. `?format=text` supported. | PRINTER-INSTALLER.md |
|
|
| `GET /api/printers/install-batch?printerids=1,2,3` | optional JWT | Generate a self-deleting Windows `.bat` that installs the selected printers. | PRINTER-INSTALLER.md |
|
|
| `GET /api/dashboarddefaults/display-role?fqdn=<fqdn>` | public (none) | Resolve what a display PC should show (role `dashboard`/`lobby`/`partskiosk`, frontend path, business unit). FQDN-first, IP fallback. | GE-ENFORCE-DISPLAY.md |
|
|
| `GET /api/dashboarddefaults/visitor-location?fqdn=<fqdn>` | public (none) | Resolve the business unit for a lobby display by FQDN (IP fallback). | GE-ENFORCE-DISPLAY.md |
|
|
|
|
The `geenforce.fetch` and `geenforce.report` scopes accept both `X-API-Key` and
|
|
`Authorization: Bearer` transports, the same managed-token pattern the collector
|
|
uses (see COLLECTOR-INTEGRATION.md for how to mint, deploy, and rotate a scoped
|
|
token). A fetch token may be further resource-bound to specific scopes; a bound
|
|
token is denied (403 on manifest, 404 on payload) anything outside its scopes.
|
|
|
|
---
|
|
|
|
## 2. Import API
|
|
|
|
The import surface (an admin PAT plus `X-Import-Mode` to preserve legacy
|
|
timestamps) lets a script load an entire legacy database through the same
|
|
endpoints the UI uses. It is documented in full, per resource, in **IMPORT-API.md**
|
|
and is not duplicated here. The dashboarddefaults import fields (FQDN-preferred
|
|
keying) are covered there as well.
|
|
|
|
---
|
|
|
|
## 3. Core UI API
|
|
|
|
Everything else is the core UI API: the endpoints the Vue frontend calls. As a
|
|
rule these are JWT-authenticated (a login token or a managed Personal Access
|
|
Token) and versioned by the plugin contract (`__contract_version__`; the
|
|
current value is in [PROJECT-MAP.md](PROJECT-MAP.md), which is generated). Behavior and stability guarantees are in **CONTRACT-STABILITY.md**;
|
|
sister sites should pin tight `core_version` ranges until the contract reaches
|
|
1.0.
|
|
|
|
Two auth patterns dominate the reads:
|
|
|
|
- **Public (no token ever).** The endpoints below are reachable with no
|
|
credential at all. This is the surface a firewall or deployment reviewer asks
|
|
about, so it is enumerated in full.
|
|
- **Optional JWT (`jwt_required(optional=True)`).** Nearly every core and plugin
|
|
GET (list / detail / report / dashboard-summary) is optional-auth: it serves
|
|
reads anonymously and only requires a JWT for writes. There are well over a
|
|
hundred of these; rather than reprint them, enumerate them from the live spec
|
|
at `/api/docs` (filter to the `GET` operations). All product reports
|
|
(`/api/reports/*` and every plugin `.../report*`) are optional-auth by the same
|
|
convention.
|
|
|
|
Every mutating endpoint (POST / PUT / PATCH / DELETE) requires a JWT and is
|
|
gated by `require_role` or `require_permission`; none are public.
|
|
|
|
Two GETs deliberately break the optional-auth convention and require a
|
|
permission, because what they return is not asset metadata but a file that
|
|
carries value or liability of its own:
|
|
|
|
| Endpoint | Requires | Why |
|
|
|---|---|---|
|
|
| `GET /api/applications/package/<filename>` | `applications.view` | Licensed vendor installers. An anonymous URL is a redistribution channel. |
|
|
| `GET /api/warranty/proof/<filename>` | `warranty.view` | Invoices and certificates carry pricing and a service tag. |
|
|
|
|
Their sibling upload/delete routes are `applications.edit` / `warranty.edit`
|
|
like any other mutation.
|
|
|
|
### Fully public endpoints (auth = none)
|
|
|
|
| Endpoint | Purpose |
|
|
|---|---|
|
|
| `POST /api/auth/login` | Obtain a JWT. |
|
|
| `GET /api/setup/needs-admin` | First-run check: does the instance have zero users. |
|
|
| `POST /api/setup/create-admin` | First-run only; creates the first admin, then 403s forever. |
|
|
| `GET /api/settings/map-blueprint/<filename>` | Serve the floor-map blueprint image. |
|
|
| `GET /api/settings/branding/<filename>` | Serve site branding assets (logo, etc.). |
|
|
| `GET /api/settings` and `GET /api/settings/<key>` | Read-only, and only the public allowlist: the `branding` and `map` categories, a few named site keys, plus any key a plugin declares `public` in `get_settings_defaults` (e.g. `printedparts_label_prefix`, which the logged-out parts kiosk renders). Every other key answers 404 to an anonymous caller. |
|
|
| `GET /api/models/image/<filename>` | Serve a model image. |
|
|
| `GET /api/applications/image/<filename>` | Serve an application image (tiles render before login). |
|
|
| `GET /api/dashboard/navigation` | Public navigation tree. |
|
|
| `GET /api/dashboard/health` | Liveness / health probe. |
|
|
| `GET /api/plugins/enabled` | List enabled plugins (no claims used). |
|
|
| `GET /api/dashboarddefaults/display-role` | Display role resolution (see section 1). |
|
|
| `GET /api/dashboarddefaults/visitor-location` | Lobby business-unit resolution (see section 1). |
|
|
| `GET /api/employees/search`, `/lookup/<sso>`, `/lookup` | Employee directory lookups (kiosk / sign-in flows). |
|
|
| `GET /api/employees/photo/<filename>` | Serve an employee photo. |
|
|
| `GET /api/notifications` (and `/types`, `/<id>`, `/active`, `/calendar`, `/dashboard/summary`, `/employee/<sso>`, `/shopfloor`) | Read shop-floor notifications for the public display and kiosks. |
|
|
| `GET /api/slides/feed` | Slide feed for the lobby display and screensaver. |
|
|
| `GET /api/slides/img/<surface>/<filename>` | Serve a slide image. |
|
|
| `GET /api/printedparts/image/<filename>` | Serve a printed-part image. |
|
|
| `GET /api/printedparts/kiosk/item/<itemcode>` | Kiosk part lookup (deliberately open; a kiosk carries no JWT). |
|
|
| `POST /api/printedparts/kiosk/take` | Kiosk part checkout (deliberately open, per decision record). |
|
|
|
|
---
|
|
|
|
## See also
|
|
|
|
- `docs/adr/README.md` - architecture decision records index.
|
|
- `docs/DEPLOY.md` - deployment; the public-endpoint inventory in section 3 above
|
|
is the site-exposure surface a deploy reviewer needs.
|
|
- `docs/PLUGINS.md` - the plugin catalog.
|
|
- Contract docs: GE-ENFORCE-CLIENT.md, geenforce-api-cutover.md,
|
|
COLLECTOR-INTEGRATION.md, PRINTER-INSTALLER.md, GE-ENFORCE-DISPLAY.md,
|
|
IMPORT-API.md, CONTRACT-STABILITY.md.
|