Saltar a contenido

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:

  • segmentId es ú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[].panelId reciben 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 configuration con rutas configuration y configuration/:segmentId
  • Widget settings con sectionsPath: /api/v1/settings/panels/{panelId}
  • El framework ensambla estas pantallas automáticamente; no hace falta declararlas en un home.py del 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 de panelId raíz; unicidad (panelId, segmentId) por panel.
  • CI: ./scripts/validate-plugin-manifests.sh valida todos los configuration/manifest.json.
  • Tests: framework/tests/test_configuration_*.py, test_platform_settings.py; frontend settingsNavigation.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 widgets parameters; segmentos solo-tabla devuelven 405.

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).

Ver ADR 020, ADR 029 y ADR 019.