Saltar a contenido

ADR 010: Módulo IO (transports y dominio)

Estado

Aceptado — 2026-06 · Implementación parcialapirest; 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:

  1. Transports: cómo entran peticiones (REST, MCP, WS) y cómo salen hacia sistemas externos (webhooks).
  2. 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 / apirest2mcp en 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

  1. Los plugins Independiente exponen negocio vía api_router() y opcionalmente register_mcp_tools / register_ws_namespaces / register_listeners / register_observers; no implementan servidor HTTP propio.
  2. Los handlers MCP invocan la misma capa de servicio que los endpoints REST del plugin (regla de oro ADR 006).
  3. webhooks entrega hacia URLs externas; la configuración de endpoints vive en framework. No sustituye events entre plugins internos.
  4. apirest2mcp es preferible a escribir handlers MCP a mano cuando el contrato REST ya está estable.
  5. Events, listeners, observers, notifications y broadcasting siguen ADR 021: cero listeners = no-op; sin imports cruzados entre plugins.

Integración con auth

  • apirest, mcp y ws pasan 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/ hacia io/apirest/ cuando se implemente el paquete nominal; canales de notification más allá de log y 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.py
  • framework/cortex_framework/api/routes.py
  • framework/cortex_framework/io/