ADR 010: Módulo IO (transports y dominio)¶
Estado¶
Aceptado — 2026-06 · Implementación parcial — apirest; mcp y ws; dominio (events, observers, notifications, broadcasting, middleware) en beta (ADR 021); webhooks / apirest2mcp en diseño
Relacionado con ADR 001, ADR 006 (MCP como submódulo), ADR 021 (IO de dominio), contexto-proyecto.md (taxonomía Dependiente).
Contexto¶
La pizarra de arquitectura clasifica como Dependiente todo lo que no es dominio de negocio. La capa IO agrupa:
- Transports: cómo entran peticiones (REST, MCP, WS) y cómo salen hacia sistemas externos (webhooks).
- Dominio entre plugins: cómo se publican hechos de negocio y se entregan avisos o push a la UI sin que un plugin importe a otro (ADR 021).
Hoy cortex_framework/api/ concentra REST; cortex_framework/io/ agrupa MCP, WebSocket y el dominio entre plugins (events, observers, notifications, broadcasting, middleware). Webhooks y apirest2mcp siguen en diseño.
Fuente del diagrama: docs/diagrams/adr/010-modulo-io-01.mermaid.
Decisión¶
Ubicación¶
Módulo interno cortex_framework.io — siempre cargado; no es un plugin opcional del catálogo.
flowchart TB
subgraph io [cortex_framework.io Dependiente]
REST[apirest]
MW[middleware]
MCP[mcp]
WS[ws]
EV[events listeners]
OBS[observers]
NT[notifications]
BC[broadcasting]
WH[webhooks]
BR[apirest2mcp]
end
subgraph consumers [Consumidores]
UI["Panel React"]
AG[Agente panel WS]
EXT[Sistemas externos]
end
subgraph plugins [Plugins Independientes]
PLG[REST MCP listeners observers]
end
UI --> REST
AG --> WS
AG --> MCP
MCP --> BR
BR --> REST
REST --> MW
MW --> PLG
PLG --> EV
EV --> PLG
EV --> NT
EV --> BC
BC --> WS
NT --> WH
WH --> EXT Leyenda: Capa IO del framework (Dependiente). Actores: panel por REST; agente de panel por WS (chat) y MCP (tools in-process); externos por webhooks. Plugins registran handlers REST,
register_mcp_tools,register_listeners,register_observers. Estado:apirest+mcp+ws+ dominio (beta ADR 021); webhooks /apirest2mcpen diseño.
Submódulos¶
| Submódulo | Responsabilidad | Estado |
|---|---|---|
apirest | FastAPI /api/v1, ensamblado de routers de plugins, guards (require_plugin_enabled, auth) | Implementado — framework/cortex_framework/api/app.py |
middleware | Pipeline ordenado del borde HTTP (MiddlewarePipeline, rate limit) | Implementado (beta) — io/middleware/ |
events | Dispatcher de hechos de dominio; registro de listeners | Implementado (beta) — io/events/ |
observers | Ciclo de vida de datos del plugin dueño (emiten events) | Implementado (beta) — io/observers/ |
notifications | Entrega multi-canal de avisos (canal log incluido) | Implementado (beta) — io/notifications/ |
broadcasting | Push de dominio a suscriptores de canal (fachada; enlazar a ws) | Implementado (beta) — io/broadcasting/ |
webhooks | Suscripciones a URLs externas, firma HMAC, reintentos (canal de notification) | Diseño |
mcp | Servidor MCP HTTP JSON-RPC, McpToolRegistry, hook register_mcp_tools (ADR 006) | Implementado (beta) — framework/cortex_framework/io/mcp/ |
ws | WebSocket /api/v1/ws, WsNamespaceRegistry, hook register_ws_namespaces | Implementado (beta) — framework/cortex_framework/io/ws/ |
apirest2mcp | Generación/adaptación de tools MCP desde contratos OpenAPI o handlers REST existentes — sin duplicar reglas de negocio | Diseño |
Reglas¶
- Los plugins Independiente exponen negocio vía
api_router()y opcionalmenteregister_mcp_tools/register_ws_namespaces/register_listeners/register_observers; no implementan servidor HTTP propio. - Los handlers MCP invocan la misma capa de servicio que los endpoints REST del plugin (regla de oro ADR 006).
webhooksentrega hacia URLs externas; la configuración de endpoints vive en framework. No sustituye events entre plugins internos.apirest2mcpes preferible a escribir handlers MCP a mano cuando el contrato REST ya está estable.- Events, listeners, observers, notifications y broadcasting siguen ADR 021: cero listeners = no-op; sin imports cruzados entre plugins.
Integración con auth¶
apirest,mcpywspasan por ADR 005 cuando auth esté activo.- Rutas públicas compartidas: health, ready, docs, OpenAPI, discovery OAuth (modo interno).
Fuera de alcance fase 1¶
- GraphQL u otros transports.
- Cola de mensajes distinta de Redis para webhooks (ADR 009 evalúa backing store).
- MCP stdio en producción (solo dev local).
- Bus de datos y hooks de puertos entre plugins (posterior a ADR 021).
Consecuencias¶
- Positivas: frontera clara entre plataforma IO y plugins de negocio; un solo lugar para middleware transversal y relevo de dominio.
- Negativas: refactor de
api/haciaio/apirest/cuando se implemente el paquete nominal; canales de notification más allá delogy fan-out WS de broadcasting pendientes.
Referencias¶
- ADR 006
- ADR 021
- Guía: Eventos de dominio
- Diagrama Lucid:
docs/diagrams/adr/010-modulo-io-01.mermaid framework/cortex_framework/api/app.pyframework/cortex_framework/api/routes.pyframework/cortex_framework/io/