feat: real plugin system with loadable instances + OpenBao secrets (v1.17.0)

Generalize the half-built discovery plugins into a real plugin system: plugin
TYPES (the plugins/<category>/<type>.js modules with manifests) and loadable,
configurable, multi-copy plugin INSTANCES (PluginInstance ORM model) managed
from a dedicated /plugins page and /api/plugins API, with per-instance secrets
in OpenBao at secret/plugins/<id>/conf.

- plugin_registry.js: getTypes/getModule/splitConfig/mask + required-field helpers
- PluginInstance model (Sequelize): id/pluginType/category/name/slug(unique)/
  enabled/cron/config(json, non-secret)/lastRun*; registered in models/index.js
- plugin_secrets.js: read/write/remove/mergeForRun over @simpleworkjs/bao-conf
- scheduler.js: schedules from the DB registry; per-instance stable BullMQ
  JobScheduler ids (plugin:<id>) for load/unload; legacy migration from
  conf.discovery.plugins on first boot (idempotent, empty-table-guarded)
- api_plugins.js (replaces routes/plugins.js): types/list/get/create/update/
  secrets/test/load/unload/run/delete/runs; admin-gated; secrets always masked
- /plugins page (plugins.ejs) + nav; Agents & Scheduler tab removed from
  /directory; /docs/agents aliased to /docs/plugins
- proxmox/unifi/nmap gained manifests (configSchema/validate/run alias)
- tests/plugins.test.js: registry unit + plugin_secrets (mocked bao-conf) +
  PluginInstance model round-trip/unique-slug
- docs (plugins.md, vault.md, _config.yml, API.md) + 1.16.1 -> 1.17.0

Requires theta-suite >= v1.30.1 for the sso-broker secret/plugins/* grant;
fails-soft with a clear error if absent.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-01 20:33:57 -04:00
parent 21a56dce50
commit cec0d92c25
23 changed files with 1679 additions and 326 deletions
+4 -1
View File
@@ -107,7 +107,10 @@ app.use('/api/oauth', middleware.auth, oauthApiRouter);
app.use('/api/oauth/client', middleware.auth, require('./routes/oauth_client'));
app.get('/.well-known/openid-configuration', discovery);
app.use('/api/webhook', require('./routes/webhook'));
app.use('/api/plugins', middleware.auth, require('./routes/plugins'));
// Plugin instances — loadable/unloadable, configurable plugin copies with
// per-instance secrets in OpenBao (secret/plugins/*). Admin-only (gated inside
// the router to app_sso_admin / app_sso_directory_admin).
app.use('/api/plugins', middleware.auth, require('./routes/api_plugins'));
// OpenBao vault API. The broker mints a server-side scoped token per user
// (per-user user-<uid> or, for admins, sso-admin), enforces the path prefix