Saltar a contenido

ADR 025: Composición por caso de uso (patrón producto ensamblado)

Estado

Aceptado — 2026-07 (reclasificado: decisión de producto, no SPI de plataforma)

Relacionado con ADR 023, ADR 024 y ADR 021.

Contexto

Cortex HIVE es una plataforma genérica para ensamblar productos (unosportclub, coworking, etc.) mediante plugins instalables. El SPI (requires, optional_requires, provides) vive en cortex-core; el framework valida descriptores en boot (validate_plugin_dependencies) sin conocer grafos de producto.

core/cortex_core/plugin_graph.py expone solo tipos genéricos (PluginGraphNode, BundleProfile) y utilidades (transitive_requires, validate_bundle_closure, detect_requires_cycles). No contiene PLUGIN_GRAPH ni perfiles de UnoSportClub.

Esta ADR fija el patrón de ensamblado (paquete products/* como extensibilidad esperada, grafo, bundles, CI). El loader no lee composition.py en runtime. Los verticales concretos se documentan en casos de uso:

  • Reservas — sandbox PMV en cortex-product-unosportclub (UnoSportClub); valida el framework hacia el PMV, no producto comercial terminado.
  • Proptech — diseño desde PropTech Platform.

Documentación: casos-de-uso/ (Reservas, Proptech).

Árbol por capas

Capa Plugins
Fundación clients, resources, payments, discounts
Catálogo pricing
Operaciones booking, sales
Extensión events, store, subscriptions
Finanzas accounting, billing
Plataforma ai-agents

Grafo de dominio (caso Reservas — UnoSportClub)

Fuente machine-readable: products/unosportclub/cortex_product_unosportclub/composition.py (REFERENCE_GRAPH).

plugin_id requires (hard) optional_requires provides
clients — — clients
resources — — resources
pricing resources — pricing
booking resources clients, pricing, payments, discounts booking
payments — — payments
sales clients, payments pricing, discounts sales
events booking, clients sales events
discounts — — discounts
accounting — payments, sales accounting
store — sales store
subscriptions clients payments subscriptions
billing clients payments, accounting billing
ai-agents — booking, clients, payments ai-agents

Leyenda:

  • requires: boot falla en CORTEX_PLUGIN_DEPS=strict si el proveedor no está enabled.
  • optional_requires: el plugin carga; UI y flujos consultan capabilities y degradan (patrón reservation-flow).
  • provides: capability indexada en GET /api/v1/control/capabilities.

Namespaces UI vs plugins de dominio

Los namespaces operations y admin son generativos (mecanismo de plataforma): el framework los materializa con ensure_panel() cuando plugins habilitados registran módulos con ese panel_id.

La convención de qué módulos van en cada namespace para el caso Reservas (UnoSportClub) es decisión del caso de uso — ver bundles.

panel_id Origen Rol (sandbox Reservas — ilustrativo)
operations Generativo Operación diaria
admin Generativo Parametrización y finanzas
accounting Plugin + cortex.panels Contabilidad — módulo home (resumen) + ledger (operación vía register_resources)
control Framework embebido Plataforma (siempre activo)
trainer Plugin dedicado Portal entrenador

Un producto ensambla pip extras del paquete cortex-product-unosportclub + plugins activos en state store.

Integración permitida

Mecanismo Uso
HTTP /api/v1/{namespace} Lectura/escritura entre dominios
Capabilities API UI condicional y degradación graceful
Events / listeners (ADR 021) Reacción desacoplada (ej. booking.confirmed → accounting)
MCP tools Agentes y automatización

Prohibido: import Python entre paquetes cortex_plugin_* de distintos plugins.

Recetas de producto (bundle profiles)

Definidas en BUNDLE_PROFILES del paquete cortex-product-unosportclub:

Perfil Propósito
operations-core Operación diaria: clientes, recursos, reservas, pagos, tarifas
operations-full operations-core + descuentos + eventos
admin-finance Finanzas admin: clientes, recursos, pagos, tarifas, ventas, facturación
sports-club-full Producto deportivo completo (perfil de referencia)
coworking-minimal Segundo producto demo: solo recursos + reservas (genericidad)

Extras pip: pip install "cortex-product-unosportclub[sports-club-full]". El meta-paquete cortex re-exporta alias deprecados (cortex[operations-core]).

Activación en caliente y paneles host

Los paneles dedicados (accounting, trainer, …) registran en boot:

  1. configure_panel() → módulo home (y metadata del shell).
  2. register_resources() → módulos operativos (ej. ledger en Contabilidad).

Si el superadmin activa el plugin sin reiniciar el API, activate_pending_plugins() debe repetir el paso 2 (y register_forms si aplica). De lo contrario el panel muestra solo Inicio en el sidebar. Implementación: framework/cortex_framework/control/runtime_activation.py.

Validación

Capa Qué valida
CI products/unosportclub/tests Descriptores == REFERENCE_GRAPH; bundles cerrados; sin ciclos; sin imports cruzados
Boot validate_plugin_dependencies requires hard según CORTEX_PLUGIN_DEPS (framework, agnóstico de producto)
Boot (warn) optional_requires ausentes — log, no fail
Hot enable panel host register_resources + register_forms vía activate_pending_plugins

Consecuencias

  • Nuevo plugin en caso Reservas: actualizar REFERENCE_GRAPH, descriptor, tests de composición y dependency-contracts.
  • Segundo producto (coworking-minimal) demuestra que UnoSportClub no es blueprint de arquitectura de plataforma.
  • accounting y billing pueden evolucionar hacia integración por events sin requires circular.