feat(cabana): read-only Plugins screen with installed plugins

- GET /plugins (backend.view_plugins, superusers always pass) lists the
  plugins from party.Installed, or party.Activated IDs for older builds,
  with the built framework version and whether the registry is configured
- Settings -> System -> Plugins entry with the new SettingsEntry.path,
  added only for principals allowed to open it
- PluginsView at /system/plugins with an Installed tab (reka-ui Tabs);
  settings panel, rail, breadcrumbs and page title know the route
- OpenAPI and SPA types regenerated; contract, token-class and
  conformance inventories list the route; en/pl strings; docs
This commit is contained in:
Jakub Zych
2026-10-29 19:05:46 +01:00
parent 0418900122
commit c4b1ac4076
27 changed files with 998 additions and 12 deletions

View File

@@ -1191,6 +1191,21 @@
],
"type": "object"
},
"cabana.Envelope-cabana_PluginsOverview": {
"properties": {
"data": {
"$ref": "#/components/schemas/cabana.PluginsOverview"
},
"meta": {
"$ref": "#/components/schemas/cabana.SuccessMeta"
}
},
"required": [
"data",
"meta"
],
"type": "object"
},
"cabana.Envelope-cabana_RelationMutationResult": {
"properties": {
"data": {
@@ -1895,6 +1910,61 @@
],
"type": "object"
},
"cabana.InstalledPlugin": {
"properties": {
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"latest": {
"type": "string"
},
"latestFramework": {
"type": "string"
},
"listed": {
"type": "boolean"
},
"module": {
"type": "string"
},
"name": {
"type": "string"
},
"package": {
"type": "string"
},
"source": {
"type": "string"
},
"updateAvailable": {
"type": "boolean"
},
"updateCommand": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"description",
"id",
"latest",
"latestFramework",
"listed",
"module",
"name",
"package",
"source",
"updateAvailable",
"updateCommand",
"version"
],
"type": "object"
},
"cabana.LangBundle": {
"additionalProperties": {
"$ref": "#/components/schemas/cabana.MessageForms"
@@ -2453,6 +2523,28 @@
],
"type": "object"
},
"cabana.PluginsOverview": {
"properties": {
"framework": {
"type": "string"
},
"plugins": {
"items": {
"$ref": "#/components/schemas/cabana.InstalledPlugin"
},
"type": "array"
},
"registry": {
"$ref": "#/components/schemas/cabana.RegistryState"
}
},
"required": [
"framework",
"plugins",
"registry"
],
"type": "object"
},
"cabana.RecordAction": {
"properties": {
"confirm": {
@@ -2562,6 +2654,21 @@
],
"type": "object"
},
"cabana.RegistryState": {
"properties": {
"enabled": {
"type": "boolean"
},
"status": {
"type": "string"
}
},
"required": [
"enabled",
"status"
],
"type": "object"
},
"cabana.RelationColumn": {
"properties": {
"key": {
@@ -2881,6 +2988,10 @@
},
"order": {
"type": "integer"
},
"path": {
"description": "Path is the admin SPA route an entry of the admin's own opens (the\nPlugins screen, /system/plugins); omitted for plugin entries.",
"type": "string"
}
},
"required": [
@@ -4170,6 +4281,52 @@
]
}
},
"/plugins": {
"get": {
"description": "The plugins the application was built with, in summer.yaml order, with the name, description, version and source summer build baked in (only the ID for an application built before plugin metadata existed), the framework version the application was built with and whether the plugin registry is configured (registry.enabled false and registry.status disabled when plugins.registry_url is empty). Requires backend.view_plugins (superusers always pass).",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/cabana.Envelope-cabana_PluginsOverview"
}
}
},
"description": "OK"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
}
}
},
"description": "Unauthorized"
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
}
}
},
"description": "Forbidden"
}
},
"security": [
{
"BackendBearer": []
}
],
"summary": "Installed plugins",
"tags": [
"admin"
]
}
},
"/settings": {
"get": {
"responses": {