Integración con el framework¶
Cómo un plugin pasa del código fuente a rutas HTTP, manifests CUS y navegación en el shell React.
Flujo end-to-end¶
sequenceDiagram
participant Dev as Desarrollador
participant EP as EntryPoint_cortex.plugins
participant Store as PluginStateStore
participant Loader as plugins_loader
participant Panel as ensure_panel
participant API as FastAPI_api_v1
Dev->>EP: pyproject.toml + create_plugin
EP->>Loader: discovery al arranque
Store->>Loader: ids activos desde PG
Loader->>Loader: register_* hooks por plugin
Loader->>Panel: materializa panel_id
Loader->>API: monta api_router por plugin Discovery¶
El framework encuentra plugins por (orden de precedencia; sideload gana):
- Entry points
cortex.pluginsen paquetes instalados (uv sync, pip). - Workspace bajo
CORTEX_PLUGINS_ROOT(default:plugins/del monorepo si existe). - Sideload con
CORTEX_PLUGIN_DIRS(solo desarrollo; override por id).
Código: framework/cortex_framework/plugins/discovery.py.
Hosts dedicados: entry point cortex.panels (ver ADR 011).
Activación¶
| Fase | Qué ocurre |
|---|---|
| Instalación | El paquete entra al catálogo (descubrible por entry point) |
| Activación | Superadmin habilita en /control/plugins → persiste en PostgreSQL |
| Bootstrap | Solo plugins activos ejecutan hooks y montan routers |
| Hot reload | Cambios de activación pueden requerir reinicio si requiresRestart: true |
Detalle: Activación de plugins.
Orden de bootstrap¶
flowchart TB
C[Control embebido]
P[Plugins activos cortex.plugins]
H[Hooks register_*]
E[ensure_panel namespaces generativos]
M[merge_panel_infrastructure]
V[validate_panels]
C --> P --> H --> E --> M --> V - Control — panel de plataforma siempre presente (
bootstrap_control_panel). - Plugins activos — instancia cada
create_plugin(). - Hooks — UI, MCP, WS, listeners, observers, settings.
- Paneles generativos —
ensure_panel("operations")(y similares) al primer aporte. - Infraestructura — widgets, layouts, módulo
configurationpor panel. - Validación — cada módulo CUS referencia un
panel_idexistente.
Código: framework/cortex_framework/plugins/loader.py, framework/cortex_framework/panels/registry.py.
Paneles generativos y namespaces¶
Un panel (panel_id) es un namespace de composición: ruta base, navegación y dashboards ensamblados desde contribuciones de plugins. El nombre del panel es decisión del plugin (contributes_panels en el descriptor, o entry point cortex.panels para hosts dedicados). El framework no mantiene un catálogo fijo de panels de negocio.
| Mecanismo | panel_id | Origen |
|---|---|---|
| Plataforma | control | Framework (siempre activo) |
| Generativo | operations, admin, samples | Shell vacío; plugins habilitados inyectan módulos |
| Host dedicado | Definido por el plugin | Entry point cortex.panels + configure_panel |
En el sandbox Reservas (caso de uso UnoSportClub), plugins como accounting o trainer pueden aportar hosts dedicados si están habilitados. No existe panel client — el plugin clients opera en operations.
Convención operations vs admin (ADR 019)¶
| Namespace | Rol | Ejemplo en sandbox Reservas |
|---|---|---|
operations | Operación diaria | booking, clients, resources |
admin | Parametrización, finanzas | sales, billing, payments, pricing |
La asignación módulo → namespace es convención del caso de uso ensamblado (ADR 025), no una regla del framework. Otro vertical podría usar otros panel_id.
Un mismo plugin puede registrar en varios namespaces (módulos, widgets o settings).
flowchart TB
subgraph namespaces [Namespaces generativos]
OP[operations]
AD[admin]
end
subgraph opMods [Modulos operacion]
BK[booking]
CL[clients]
end
subgraph admMods [Modulos parametrizacion]
SL[sales]
BL[billing]
PY[payments]
end
OP --> opMods
AD --> admMods Ver ADR 019 y Panel namespaces y composición.
Contribuir un módulo¶
from cortex_framework.ui import ResourceBuilder, register_resource
def register_resources(registry: ResourceRegistry) -> None:
def configure(builder: ResourceBuilder) -> None:
(
builder.id("items")
.title("Ítems")
.api_base("/api/v1/mi-modulo")
.list_path("/api/v1/mi-modulo/items")
.module_path("items")
.nav_group("catalog", nav_sort=20)
.pages(list=True)
.table(lambda t: t.columns(lambda c: c.text("name", "Nombre")))
)
register_resource(registry, "operations", "mi-modulo", configure)
Al registrar, el framework:
- Crea el namespace
operationssi no existe (ensure_panel). - Añade el módulo
mi-moduloal manifest del panel. - Expone dashboards y forms vía
/api/v1/panels/...y/api/v1/ui/....
Runtime HTTP¶
Tras el bootstrap, cada petición REST ejecuta solo el código en api_router() — los hooks ya corrieron una vez.
El shell React (web-shadcn) consume manifests y dashboards; los widgets llaman a tus rutas REST.
sequenceDiagram
participant Shell as web_shadcn
participant API as FastAPI
participant Plugin as plugin.py
Shell->>API: GET panels/operations/modules/.../manifest
Shell->>API: GET ui/dashboards/{id}
Shell->>API: GET /api/v1/mi-modulo/items
API->>Plugin: handler list_items Entry point opcional cortex.panels¶
Para namespaces con identidad propia (marca, tema, scopes), un plugin puede exportar configure_panel(PanelBuilder). El loader llama a load_panel_hosts() después de materializar namespaces generativos, solo para hosts que aún no existen.
No uses cortex.panels para operations ni admin — el framework ya aplica metadata de shell vía módulos integrados.
Plugin de demostración¶
plugins/helloworld es sandbox de plataforma (panel samples, To-Do demo). No está en el catálogo de dominio: ver API interna del framework.
Siguiente paso¶
Primer plugin — tutorial paso a paso desde la plantilla.