Ciclo de vida del plugin¶
Entiende cuándo se ejecuta tu código: en el bootstrap de la API (arranque) o en cada petición HTTP (runtime).
Cuándo leer esta página¶
- Necesitas saber qué hooks existen y en qué orden se invocan.
- Quieres distinguir registro de UI (una vez) de lógica de negocio (por request).
- Vas a montar un panel host o contribuir a uno existente.
Discovery¶
El framework descubre plugins por:
- Entry points
cortex.pluginsenpyproject.toml(pip / workspace uv). - Sideload con
CORTEX_PLUGIN_DIRS=/ruta/extra(override por id). - Filtro
CORTEX_ENABLED_PLUGINS(lista separada por comas o*).
Los panel hosts se descubren aparte con entry point cortex.panels.
Orden de bootstrap¶
flowchart TB
H[Panel hosts cortex.panels]
P[Plugins cortex.plugins]
R[Hooks por plugin]
V[validate_panels]
H --> P --> R --> V - Panel hosts —
configure_panel(PanelBuilder)registra panels enPanelRegistry. - Plugins de negocio —
create_plugin()instancia cada plugin activo. - Hooks — por cada módulo importado, si el hook existe se invoca con su registry.
- Validación — cada módulo UI referencia un
panel_idexistente.
Hooks de bootstrap¶
| Hook | Registry | Qué publica |
|---|---|---|
register_resources | ResourceRegistry | Manifest + dashboards + forms (recomendado) |
register_dashboards | DashboardRegistrar | JSON en ui/ (legacy) |
register_forms | FormRegistrar | Formularios sueltos |
register_settings | SettingsRegistry | Secciones de configuración |
register_layouts | LayoutRegistrar | Fragmentos de layout (merge) |
register_reports | ReportRegistry | Reportes exportables |
register_widgets | WidgetRegistrar | Widgets sueltos |
register_render_hooks | RenderHookRegistrar | Slots en el shell |
register_panel_plugins | PanelPluginRegistrar | Extensión del builder del host |
Deprecado
register_panels está deprecado. Usa entry point cortex.panels y configure_panel.
Prioridad de UI¶
Si el paquete exporta register_resources, el loader no ejecuta register_forms ni register_dashboards por separado — el ResourceBuilder ya registra forms y dashboards.
Los hooks deben reexportarse en el __init__.py del paquete del plugin; el loader importa el módulo raíz.
Bootstrap vs runtime¶
| Fase | Qué ocurre | Dónde vive tu código |
|---|---|---|
| Bootstrap | Discovery, hooks, validación CUS | resources.py, provider.py, __init__.py |
| Runtime | Peticiones REST, persistencia, tenant | plugin.py → api_router() |
El shell React nunca importa tu plugin. Consume JSON por HTTP (/api/v1/panels/..., /api/v1/ui/dashboards/...).
Contrato mínimo del plugin¶
class PluginProtocol:
descriptor: PluginDescriptor
def api_router(self) -> APIRouter: ...
def resource_paths(self) -> list[str]: ...
resource_paths() declara los namespaces REST del dominio (ej. ["booking"]) para documentación y control.
Tenant¶
El tenant se resuelve por header X-Tenant-Id (configurable con CORTEX_TENANT_HEADER). No va en la ruta URL.
La URL de base de datos por tenant sigue CORTEX_DATABASE_URL_TEMPLATE, por ejemplo postgresql+asyncpg://...@localhost:5432/cortex_{tenant}.
Siguiente paso¶
- API REST — contratos de listados y errores.
- Panels — contribuir un módulo a un panel existente.
- Panel hosts — crear un panel nuevo.
Ver también ADR 007 (persistencia) y contexto del proyecto.