Plugins
Plugins
Section titled “Plugins”The Plugins panel (/plugins in super-admin) is the catalog view across the framework. Operators use it to:
- See every plugin known to the platform (whether shipped in
plugins/or published tonpm.ecommus.cloud) - Enable / disable a plugin for a specific tenant
- Pin a tenant to a specific plugin version (important for upgrade staging)
- Publish a new plugin version to the private registry (when
marketplace_publisheris on)
This is not the same as the per-tenant tenant admin’s “Plugins” page. The per-tenant page lets a tenant admin enable/disable plugins their license already includes. The super-admin panel here is the platform-wide catalog and grant layer.
Catalog source
Section titled “Catalog source”The catalog is the union of:
| Source | When |
|---|---|
plugins/ directory in this monorepo | Built-in plugins. Shipped with every customer copy. Auto-discovered at API boot. |
npm.ecommus.cloud registry | Premium plugins. Customer pulls them when their license JWT grants the licensed_plugins. |
| Customer-uploaded private plugins | (Enterprise only) the customer can publish their own plugin to a private scope @<customer>/<plugin>. |
The panel shows all three with badges (Built-in, Premium, Private).
Plugin row shape
Section titled “Plugin row shape”{ "id": "niche-booking", "scope": "@ecommus-plugin", // npm scope the package lives under "version": "2.4.1", // active version on npm.ecommus.cloud "tier_minimum": "pro", // minimum tier required "niches": ["services", "travel"], // which niches it's relevant to "default_in_packages": ["services"], // which niche packages bundle it by default "tenants_using": 17, // how many tenants currently have it enabled "supports_versions": ["2.4.1", "2.4.0", "2.3.5"], // versions still on the registry "deprecated": false, "publisher": "MediaDesign SRL", "signed_with_kid": "k1", // code-signing kid on the bundle "manifest": { /* ecommus.plugin.json snapshot */ }, "registered_at": "2026-03-12T...", "updated_at": "2026-04-28T..."}Per-tenant enable / disable
Section titled “Per-tenant enable / disable”For a tenant on the right plan + license, the operator can enable or disable individual plugins:
GET /api/super-admin/tenants/:id/plugins → list with enabled flagPOST /api/super-admin/tenants/:id/plugins/:plugin/enable { version?: "2.4.1" }POST /api/super-admin/tenants/:id/plugins/:plugin/disableServer-side checks before enabling:
- The plugin id is in the tenant’s license
licensed_plugins. If not, the route refuses with403 license_denied. - The plugin’s
tier_minimumis ≤ the tenant’s tier. Otherwise403 tier_too_low. - The plugin’s
nichescontains the tenant’s niche. Otherwise409 niche_mismatch. - If the version is pinned, the version exists on the registry. Otherwise
404 version_not_found.
Enable is idempotent — if already enabled at the same version, no-op.
When enabled, the API:
- Pulls the npm package on the customer’s install (next deploy or on-demand via
/api/admin/plugins/install) - Runs the plugin’s migrations (
ctx.registerMigration()) — idempotent via_ecommus_plugin_migrations - Subscribes the plugin’s hooks + filters to the EventBus
- Registers the plugin’s routes + admin slots
When disabled:
- The plugin’s hooks + routes are removed from the live process
- Migrations are not rolled back. Plugin code is removed from the boot path but its DB tables stay (they’re idempotent on re-enable). Manual cleanup requires a separate SQL operation per ADR-027.
Version pinning
Section titled “Version pinning”By default, customers receive the latest non-deprecated version of every plugin in their license. To stage an upgrade for a single tenant before the rollout:
POST /api/super-admin/tenants/:id/plugins/niche-booking/pin{ "version": "2.5.0-beta.1" }The pin overrides the default-latest until cleared. Use cases:
- Beta testing a new plugin version with one customer before broad rollout
- Holding a customer back on an older version because the new one breaks their custom theme overrides
- Investigating a regression — pin to the previous version while the bug is fixed
Clear with DELETE /api/super-admin/tenants/:id/plugins/:plugin/pin (returns to default-latest).
Publishing a new version (requires marketplace_publisher)
Section titled “Publishing a new version (requires marketplace_publisher)”POST /api/super-admin/plugins/:id/publishWizard flow:
- Upload — operator uploads the bundle
.tar.gz(built by the plugin’s CI, signed with the platform code-signing key) - Verify signature — server checks the bundle against
ECOMMUS_CODE_SIGNING_PUBLIC_KEY_FILE - Run smoke tests — boots a sandbox API in a container with the plugin and runs the standard plugin smoke harness (boots cleanly, registers without errors, migrations apply)
- Stage on a canary tenant — operator picks one tenant marked
canary: true(set in/tenantsdetail) and pins the new version there - Wait period — 24 h default (configurable in
/settings) — observability stack monitors error rates on the canary tenant. If errors spike >2× baseline, the publish auto-rolls-back. - Promote — after the wait, the operator clicks “promote” and the new version becomes default-latest on the registry. All tenants without a pin automatically pick it up on the next install / pm2 reload.
Publishing without marketplace_publisher is denied at the API layer. The flag is a hard gate (CLAUDE.md §0 — “publishing” requires the flag, not just plugin installation).
Deprecating + removing plugins
Section titled “Deprecating + removing plugins”POST /api/super-admin/plugins/:id/deprecate flags the plugin’s catalog row + emits a banner in the per-tenant admin UI for every tenant using it. Tenants stay on it until they explicitly migrate away — deprecate doesn’t auto-disable.
DELETE /api/super-admin/plugins/:id removes the plugin from the registry (refuses if any tenant still has it enabled). This is a high-trust action — only owner operators, audit-logged.
Plugin failure isolation
Section titled “Plugin failure isolation”A plugin failing to init() does not take the API down — it’s logged and skipped (CLAUDE.md §0.4). The panel surfaces these failures as warning banners on the affected plugin row. Drill in to see the stack trace and which customer installs are affected.
If a plugin starts failing at runtime (post-init), the per-tenant admin panel shows a yellow flag on the plugin’s settings page; the super-admin panel aggregates these into a “Plugin health” widget on the dashboard.
See also
Section titled “See also”- Overview — full panel inventory
- Tenants — tenant ↔ plugin assignment
- Plans —
marketplace_publisherflag (gates publishing) - Plugin Overview — author guide for building plugins
- License (customer-facing) —
licensed_pluginsarray - ADR-027 — plugin teardown + migration retention policy