Configuración (settings)¶
Cada plugin declara ajustes en configuration/manifest.json. El framework carga el archivo en boot, fusiona fragmentos por panelId y expone un árbol género → segmento → widgets por panel. El framework ensambla el módulo configuration en cada panel que tenga segmentos: /admin/configuration/{segmentId}, /control/configuration/{segmentId}, etc.
Diagramas: ADR 020 — manifest, ADR 029 — ensamblado por panel.
Cuándo usar¶
parameters: valores escalares de plataforma (flags, textos, números) persistidos en el store de settings.parameter_table: catálogo pequeño de filas del plugin (resource ligero) con CRUD vía API del plugin.
Manifest (contributions[])¶
Ruta fija: cortex_plugin_<id>/configuration/manifest.json. Todo manifest usa contributions[] (un elemento por panel_id; varios si el plugin inyecta en más de un namespace).
{
"pluginId": "helloworld",
"contributions": [
{
"panelId": "samples",
"groups": [
{ "id": "operations", "label": "Operaciones", "navSort": 20 }
],
"segments": [
{
"id": "demo",
"title": "Demos",
"group": "operations",
"navSort": 10,
"description": "Ajustes del módulo de demostración.",
"widgets": [
{
"type": "parameters",
"groupLabel": "General",
"fields": [
{ "name": "demo_flag", "type": "toggle", "title": "Activar modo demo" }
]
}
]
}
]
}
]
}
Multi-panel (mismo archivo, varios hosts):
{
"pluginId": "ai-agents",
"contributions": [
{
"panelId": "control",
"groups": [{ "id": "platform", "label": "Plataforma", "navSort": 10 }],
"segments": [
{
"id": "credentials",
"title": "Credenciales IA",
"group": "platform",
"widgets": [{ "type": "parameter_table", "listPath": "...", "itemPath": "...", "createPath": "...", "columns": [] }]
}
]
},
{
"panelId": "admin",
"groups": [{ "id": "automation", "label": "Automatización", "navSort": 50 }],
"segments": [
{
"id": "ai-agents",
"title": "Agentes IA",
"group": "automation",
"widgets": [{ "type": "parameter_table", "listPath": "...", "itemPath": "...", "createPath": "...", "columns": [] }]
}
]
}
]
}
Reglas:
segmentIdes único dentro de un panel (puede repetirse entre paneles distintos).- Colisión
(panelId, segmentId)entre plugins en el mismo panel → error en boot. - Sin propagación automática: solo los paneles listados en
contributions[].panelIdreciben fragmentos.
Hook register_configuration¶
Alternativa o complemento al JSON (mismo contrato que register_widgets):
def register_configuration(registry: ConfigurationRegistrar) -> None:
registry.contribute_segment("control", credentials_segment, "my-plugin")
registry.contribute_segment("admin", agents_segment, "my-plugin")
El manifest se carga primero; el hook añade fragmentos (no reemplaza).
Ensamblado del módulo por panel¶
merge_panel_infrastructure llama a assemble_configuration_module(panel_id) cuando hay segmentos para ese panel:
- Módulo
configurationcon rutasconfigurationyconfiguration/:segmentId - Widget
settingsconsectionsPath:/api/v1/settings/panels/{panelId} - El framework ensambla estas pantallas automáticamente; no hace falta declararlas en un
home.pydel plugin
Los géneros se fusionan entre plugins (como navGroups en recursos). Un segmento puede apilar varios widgets (parameters + parameter_table).
Preferencias de UI del widget settings: segmento con id *-ui y widgets parameters (p. ej. admin-ui). La API devuelve uiPrefsSegmentId en GET /settings/panels/{panelId}.
Referencia: plugins/booking/cortex_plugin_booking/configuration/manifest.json, plugins/ai-agents/.../configuration/manifest.json.
API HTTP¶
| Método | Ruta |
|---|---|
GET | /api/v1/settings/panels/{panelId} — árbol { groups, segments, uiPrefsSegmentId? } |
GET | /api/v1/settings/panels/{panelId}/{segmentId} — valores de widgets parameters |
PUT | /api/v1/settings/panels/{panelId}/{segmentId} — actualizar solo segmentos con widgets parameters |
Las tablas (parameter_table) persisten fila a fila contra las rutas declaradas en el manifest (listPath, createPath, itemPath).
Persistencia en PostgreSQL vía CORTEX_DATABASE_URL. Ver persistencia.
Validación¶
- Boot:
contributions[]obligatorio; rechazo depanelIdraíz; unicidad(panelId, segmentId)por panel. - CI:
./scripts/validate-plugin-manifests.shvalida todos losconfiguration/manifest.json. - Tests:
framework/tests/test_configuration_*.py,test_platform_settings.py; frontendsettingsNavigation.test.ts.
En local:
uv run pytest framework/tests/test_configuration_plugin_manifests.py framework/tests/test_platform_settings.py -q
npm test --workspace @cortex/panel-shadcn
PUT: solo claves declaradas en widgetsparameters; segmentos solo-tabla devuelven405.
Deprecado¶
register_settings + SettingsBuilder en extensions.py queda como shim si no hay manifest; en plugins nuevos usar solo el JSON o register_configuration.
Reglas de asignación por panel (ADR 019):
| Panel | Plugins de configuración |
|---|---|
operations | panel, booking, clients |
admin | admin, sales, billing, payments |
control | credenciales IA (ai-agents) |
accounting | accounting |
Usar contributions[] cuando un plugin deba inyectar en varios paneles (p. ej. ai-agents).