docs/PLUGINS.md listed sixteen of the seventeen bundled plugins. The missing one was endpoints - the newest, and the one another site is most likely to ask about, since it is the Fleet console and the live panels on a PC detail page. The row records the two things that are not guessable from the name: it depends on computers because an endpoint is telemetry ABOUT a PC asset rather than a second record of it, and its four permissions are split deliberately. Read is grantable to guests by the .view suffix rule; fleet, command and restart are not, and the plugin declares no override, so the command channel cannot be opened to anonymous callers by ticking a box. Ingest is called out as NOT being a route here - agent reports arrive on the generic collector route under a service token scoped collector.ingest.endpoints. Somebody looking for the ingest endpoint in this plugin will not find one. applications/ stays absent on purpose: it has no manifest and no plugin.py, so per the manifest-less rule it is core frontend surface that always ships, not a plugin a site can choose.
11 KiB
Plugins
shopdb-flask is a framework. The plugins listed here are the pieces other GE Aerospace facilities can install, build, or skip per ADR-003. Bundled plugins ship in the framework repo. External plugins live in their own repos and drop into <repo>/plugins/<name>/ at install time.
Bundled (ship with the framework)
These plugins are in plugins/ in this repo. Enable per site with flask plugin install <name>.
| Plugin | Tracks | Notes |
|---|---|---|
machines |
Manufacturing machinery: 5-axis mills, lathes, broachers, heat treatment ovens | Manually entered. See ADR-005. Subtype tables for FOCAS / CLM / MTConnect controller protocols (planned). |
computers |
Shop-floor PCs and engineering workstations | Fed by the PXE pipeline collector per ADR-006. |
printers |
Network and shop-floor printers | Public installer map page + fleet install contract (/api/printers/install-list, /pc-default, /install-batch; see PRINTER-INSTALLER.md). Optional Zabbix integration for supply tracking. Legacy PrinterData retiring per ADR-001. |
network |
Switches, routers, access points, IDFs as locations | Asset-only; cleanest of the bundled set. |
usb |
USB devices issued to shop-floor users | Lightweight checkout / check-in, self-hosted tables or an existing cmmc_usb database. Optional logged-out kiosk (/usb-kiosk, off by default) so somebody at the drive cabinet can take and return a drive without a ShopDB login, attributed to a scanned badge. |
notifications |
Shop-floor notifications, recognitions, kiosk feed | Used by ShopfloorDashboard.vue. |
measuringtools |
Metrology and inspection instruments: calipers, micrometers, thread/bore/height gages, indicators | Per ADR-005. Calibration lifecycle with derived status. First plugin built on the matured scaffold; its walkthrough is PLUGIN-GUIDE.md. Ships default_enabled: false. |
employees |
Read-only employee directory lookup | Backed by a separate HR database. Ships default_enabled: false. |
geenforce |
GE-Enforce manifest store: imaging PC-type scopes and their install manifests (apps, scripts, files, registry, version gates) | Per ADR-012. Served to the GE-Enforce client as JSON. Requires GE-Enforce lib >= 2.6 on target PCs. Ships default_enabled: false. |
knowledgebase |
Knowledge Base articles linking to external resources | Lightweight article store. |
printedparts |
3D-printed parts inventory | Kiosk checkout / check-in. Ships default_enabled: false. |
slides |
Slides for the lobby display and shop-floor screensaver | Upload / reorder / delete per surface. Management gated on the slides.manage permission, grantable to non-admin curators; display routes are public. |
tools |
Technician utilities: barcode and QR label generation, unit conversions, Secure Send | Mostly browser-side by design, so an air-gapped bench gets them with no network. Secure Send is the exception and is why this plugin has a blueprint, a table and a migration chain: see SECURE-SEND.md. |
warranty |
Asset warranty tracking | Manual entry now, Dell / Lenovo / HP provider lookups later. Derived coverage status with report buckets. |
guides |
Step-by-step procedures written in ShopDB: typed blocks, pasted screenshots, live checkboxes, tags, drafts and revision history | Content is stored as typed blocks rather than markup, so the same guide renders to screen, dark mode and paper. Readers see the PUBLISHED revision only - a technician following a procedure must not have it change under them mid-task. Checkbox ticks are per-viewer and never edit the guide. See GUIDES.md. |
endpoints |
Live endpoint telemetry for shop-floor PCs: liveness, services, processes, inventory, and curated Windows event records, reported by the ShopDB agent | Depends on computers - an endpoint is telemetry ABOUT a PC asset, never a second record of it. Adds the Fleet console plus the live panels on a PC's detail page. Four separate permissions: endpoints.view to read, endpoints.fleet for the fleet-wide console, endpoints.command to act on one endpoint, and endpoints.restart for a reboot. They are split because read access is grantable to guests and the command channel is not. Ingest is not a route in this plugin: agent reports arrive on the generic collector route and authorize on a service token scoped collector.ingest.endpoints, not a user JWT, per ADR-006. That scope doubles as the kill switch for the agent key. See FLEET-ARCHITECTURE.md. |
backups |
Per-asset configuration backups with revision history: NTLARS/DNC registry and part marker | Kind-pluggable per BACKUP-KINDS.md; a kind is one class in services/registry.py. Parseable kinds store a JSON projection and re-render to the native format on download; opaque vendor formats stay on the SFLD share with ShopDB holding metadata and the UNC pointer. Fed by the collector, so ingest authorizes on a collector.ingest service token, not a user JWT. backups.view and backups.download are separate permissions because a .reg is a restorable artifact. Not to be confused with BACKUP-RESTORE.md, which is the ShopDB database itself. |
Plugin permissions
Plugins may register their own permissions (for example slides.manage). Admins
implicitly hold them; grant them to specific roles or users to delegate curation
without admin. Each plugin's registered permissions appear in its plugin.py
get_permissions().
Building your own
Guides:
- PLUGIN-QUICKSTART.md - generate, customize, install, and test a plugin in 30 minutes using
flask plugin new. - PLUGIN-GUIDE.md - the full narrative walkthrough of building the
measuringtoolsplugin, the exemplar that exercises every current framework feature (models, per-plugin migrations, authz, hooks, frontend integration, tests). - PLUGIN-EXTERNAL-REPO.md - developing a plugin in its own repo per ADR-003: repo layout, symlink dev workflow,
core_versionpinning, and a runnable CI harness (scripts/test-external-plugin.sh) that tests the plugin against a pinned framework ref. - CONTRACT-STABILITY.md - path to contract 1.0: what is settled vs still churning, the bump rules, and how much a sister site can safely build on today.
The contract is locked in ADR-001 and versioned per ADR-002.
Quick path:
flask plugin new cameras --description "Tracks shop-floor surveillance cameras"
# edit plugins/cameras/models/cameras.py with your fields
flask plugin install cameras
Migrations (per-plugin chains)
Each plugin that owns tables carries its own Alembic chain under
plugins/<name>/migrations/, with a per-plugin version table
alembic_version_<name> independent of the core alembic_version. Ownership is
split at a fixed cutover (see ADR-008):
- The core chain (
flask db upgrade) created every table that existed through its head, including the bundled-plugin tables. Each bundled plugin's0001migration is a stamp-only no-op anchor recording that fact. - From the cutover forward, a change to a plugin's schema lands as
plugins/<name>/migrations/versions/000N_*.py, never in the core chain. The core chain is reserved for core tables. - A plugin built AFTER the cutover (e.g.
measuringtools) is different: the core chain never created its tables, so its0001is a REAL baseline that creates them, not a no-op anchor. See PLUGIN-GUIDE.md for the anchor-vs-baseline distinction.
Deploys and upgrades run flask db upgrade then flask plugin upgrade-all.
upgrade-all stamps every plugin anchor and applies any later plugin
migrations; it is idempotent. The registry (instance/plugins.json) records
which revisions each plugin has applied in migrations_applied.
Distribution conventions
For sister-site plugins (per ADR-003):
- Plugin lives in its own git repo:
<git-host>/<your-site>/<pluginname> - Adopting site clones or symlinks into their
<repo>/plugins/<name>/ - Plugin manifest declares
core_versionrange matching the framework version they target - Plugin readme explains: what it tracks, who maintains it, where to file issues
Lean per-site builds
A site ships only the plugins it chose; a site that never wants printedparts / usb / network never carries that code (see ADR-013 and ADR-014). Three layers make a build lean:
- Backend code -
scripts/build-site.sh <profile>stagesshopdb/coreplus only the chosen plugins' directories (and their hard-dependency closure). A plugin a site did not choose is absent from the backend tree. - Frontend code -
SITE_PLUGINS=machines,printers npm run build(viascripts/stage-frontend.mjs) stages only those plugins'frontend/dirs and codegens the route table. Exception: aplugins/<name>/frontend/dir with nomanifest.jsonis a CORE feature (e.g.applications), not a per-site plugin, and is ALWAYS staged regardless ofSITE_PLUGINS- otherwise a lean build would lose a core page. - Database - the shared core Alembic baseline creates every plugin's tables,
so a lean site provisions them and then drops the ones it does not use with
flask plugin prune-schema(ADR-014). Run it once at provisioning, afterflask db upgradeandflask plugin upgrade-all; see DEPLOY.md.
Menus follow the build, not a plugin flag. The sidebar nav, the settings rail, and the Displays links all gate on whether the target route was actually staged into this build (the router's own route table), not on a registry "enabled" flag. So a lean site never shows a menu entry that dead-ends on a blank page - an omitted plugin's nav item, settings cards, and kiosk links all disappear together. Shopfloor Dashboard is a core view but is gated on the notifications plugin (its only data source), so it drops when notifications is not in the build.
Naming policy
Plugin names follow the framework's naming convention (lowercase concatenated, no underscores or dashes; full words preferred over acronyms). See CONTRIBUTING.md. Plugin name collisions across sites are not enforced; the convention recommends prefixing site-specific plugins with the site code (e.g., wjsf-shippingstation) when there is risk of overlap.