Ai System Config Design

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

AI System Configuration - Design Document

Overview

Este documento describe el diseño de AISystemConfiguration que reemplaza a AppUiConfiguration como la configuración principal del sistema GoGrab Space. El objetivo es crear un PoC de un sistema de módulos dinámicos que use configuración generada por IA.

Nota: Fase de desarrollo - sin retrocompatibilidad. Enfoque directo y simplificado.

Decisiones de Diseño

Aspecto Decisión Justificación
Granularidad Híbrido (sistema base + páginas dinámicas) Flexibilidad sin complejidad excesiva
Escenario PoC Sistema de inventario para restaurante Caso concreto y representativo
Fuente de Config Prompt natural (IA interpreta texto) UX más natural para usuarios
Runtime Semi-dinámico (config base + ajustes usuario) Balance entre flexibilidad y rendimiento
Complejidad Simplificado para PoC (sin reglas condicionales) Enfocarse en flujo principal
Estrategia Reemplazar directamente (sin retrocompatibilidad) Código limpio, sin legacy

Arquitectura

Principio de Reemplazo Directo

┌─────────────────────────────────────────────────────────────────────────┐
│   REEMPLAZO DIRECTO - SIN RETROCOMPATIBILIDAD                           │
│                                                                         │
│   ELIMINAR                              NUEVO                           │
│   ════════                              ═════                           │
│   AppUiConfiguration           ──►      AISystemConfiguration           │
│   ModuleConfigurationService   ──►      AppConfigService (unificado)    │
│   Endpoint modules/config      ──►      Endpoint /api/config/ui         │
│                                                                         │
│   AISystemConfiguration:                                                │
│   ├─ navigation      (de AppUiConfiguration)                            │
│   ├─ dashboard       (de AppUiConfiguration)                            │
│   ├─ topNav          (de AppUiConfiguration)                            │
│   ├─ branding        (de AppUiConfiguration)                            │
│   ├─ generatedAt     (de AppUiConfiguration)                            │
│   ├─ version         (de AppUiConfiguration)                            │
│   │                                                                     │
│   │  + NUEVAS CAPACIDADES:                                              │
│   ├─ scenario        (metadata del caso de uso)                         │
│   ├─ generatedFrom   (info de generación IA)                            │
│   ├─ modules         (activación de módulos) ◄── REEMPLAZA ModuleConfig │
│   ├─ pages           (páginas dinámicas)                                │
│   └─ theme           (customización de tema)                            │
└─────────────────────────────────────────────────────────────────────────┘

Servicios a Eliminar/Modificar

Servicio Acción Razón
ModuleConfigurationService ELIMINAR Unificado en AppConfigService
AppConfigService MODIFICAR Agregar signals para módulos, páginas, etc.
BrowserBootstrapperService MODIFICAR Usar AppConfigService.enabledModules()
Mock API legacy endpoint ELIMINAR Todo en /api/config/ui

Integración con Sistema Existente

┌─────────────────────────────────────────────────────────────────────────┐
│                    INTEGRACIÓN CON BIBLIOTECAS CORE                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  @libs-core/module-config                                               │
│  ├── AppUiConfiguration ◄────── ELIMINAR (reemplazado)                  │
│  ├── AISystemConfiguration ◄─── NUEVO (reemplaza todo)                  │
│  ├── WidgetPlacement ◄────────── WidgetInstanceConfig EXTIENDE          │
│  └── ResolvedNavigationConfig   (se reutiliza directamente)             │
│                                                                         │
│  @libs-core/module-base                                                 │
│  ├── ModuleConfigurationService ◄── ELIMINAR                            │
│  ├── ModuleManifest              (widgets vienen de aquí)               │
│  └── ModuleEmbeddableComponent   (definición de widgets disponibles)    │
│                                                                         │
│  @libs-core/data-binding                                                │
│  └── DataBinding ◄────────────── WidgetInstanceConfig.bindings USA      │
│                                                                         │
│  @libs-core/module-integrator                                           │
│  └── BrowserBootstrapperService  (usa AppConfigService.enabledModules)  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Schema de Interfaces

AISystemConfiguration (Principal)

import type { DataBinding } from '@libs-core/data-binding';
import type { BrandingConfig } from '@libs-core/shared-models';
import type { ResolvedNavigationConfig } from './resolved-navigation-config';
import type { ResolvedDashboardConfig } from './resolved-dashboard-config';
import type { ResolvedTopNavConfig } from './resolved-topnav-config';
import type { WidgetPlacement } from './tenant-customization';

/**
 * Configuración completa del sistema.
 * Reemplaza AppUiConfiguration y ModuleConfigurationRegistry.
 */
export interface AISystemConfiguration {
  // ═══════════════════════════════════════════════════════════════════
  // Propiedades de configuración UI (antes en AppUiConfiguration)
  // ═══════════════════════════════════════════════════════════════════

  /** Configuración de navegación completa con grupos y jerarquías */
  navigation: ResolvedNavigationConfig;

  /** Configuración de dashboard con widgets y layout */
  dashboard: ResolvedDashboardConfig;

  /** Configuración de TopNav con branding */
  topNav: ResolvedTopNavConfig;

  /** Branding del tenant (logo, colores, nombre empresa) */
  branding: BrandingConfig;

  /** Timestamp de generación de esta configuración */
  generatedAt: Date;

  /** Versión del schema de configuración */
  version: string;

  // ═══════════════════════════════════════════════════════════════════
  // Nuevas propiedades para configuración IA
  // ═══════════════════════════════════════════════════════════════════

  /** Metadata del escenario/caso de uso */
  scenario: ScenarioConfig;

  /** Información sobre cómo se generó esta configuración */
  generatedFrom: AIGenerationMetadata;

  /** Módulos activos y su configuración (reemplaza ModuleConfigurationRegistry) */
  modules: ModuleActivationConfig[];

  /** Páginas dinámicas compuestas con widgets */
  pages: PageConfig[];

  /** Customización de tema (opcional) */
  theme?: ThemeCustomization;
}

ScenarioConfig

/**
 * Metadata del escenario/caso de uso.
 */
export interface ScenarioConfig {
  id: string;
  name: string;
  description: string;
  industry: string;
  tags: string[];
}

AIGenerationMetadata

/**
 * Información sobre cómo se generó la configuración.
 */
export interface AIGenerationMetadata {
  source: 'ai' | 'manual' | 'template';
  originalPrompt?: string;
  generatedAt: Date;
}

ModuleActivationConfig

/**
 * Configuración de activación de un módulo.
 * REEMPLAZA ModuleConfigurationRegistry del sistema anterior.
 */
export interface ModuleActivationConfig {
  /** ID del módulo (debe existir en registry) */
  moduleId: string;

  /** Si el módulo está activo */
  enabled: boolean;

  /** Configuración simple key-value */
  config?: Record<string, unknown>;
}

PageConfig

/**
 * Configuración de una página dinámica.
 */
export interface PageConfig {
  id: string;
  route: string;
  title: string;
  icon?: string;
  layout: PageLayoutConfig;
  widgets: WidgetInstanceConfig[];
  permissions?: string[];
}

export interface PageLayoutConfig {
  type: 'grid' | 'flex' | 'single';
  columns?: number;
  gap?: string;
}

WidgetInstanceConfig

/**
 * Instancia de widget con data bindings.
 * Extiende WidgetPlacement con integración a data-binding.
 */
export interface WidgetInstanceConfig extends WidgetPlacement {
  bindings?: DataBinding[];
}

ThemeCustomization

/**
 * Customización básica de tema.
 */
export interface ThemeCustomization {
  baseTheme: 'light' | 'dark';
  colors?: {
    primary?: string;
    secondary?: string;
    accent?: string;
  };
}

AppConfigService - Signals Unificados

// libs/core/module-config/src/lib/services/app-config.service.ts

@Injectable({ providedIn: 'root' })
export class AppConfigService {
  // Signal principal
  private configSignal = signal<AISystemConfiguration | null>(null);
  readonly configuration = this.configSignal.asReadonly();

  // ═══════════════════════════════════════════════════════════════════
  // Signals existentes (UI config)
  // ═══════════════════════════════════════════════════════════════════

  readonly navigationConfig = computed(() => this.configuration()?.navigation ?? null);
  readonly dashboardConfig = computed(() => this.configuration()?.dashboard ?? null);
  readonly topNavConfig = computed(() => this.configuration()?.topNav ?? null);
  readonly availableWidgets = computed(() => this.configuration()?.dashboard?.availableWidgets ?? []);

  // ═══════════════════════════════════════════════════════════════════
  // NUEVOS Signals para módulos (REEMPLAZA ModuleConfigurationService)
  // ═══════════════════════════════════════════════════════════════════

  /** Todos los módulos configurados */
  readonly modulesConfig = computed(() => this.configuration()?.modules ?? []);

  /** Solo módulos habilitados */
  readonly enabledModules = computed(() =>
    this.modulesConfig().filter(m => m.enabled)
  );

  /** IDs de módulos habilitados */
  readonly enabledModuleIds = computed(() =>
    this.enabledModules().map(m => m.moduleId)
  );

  /** Verificar si módulo está habilitado */
  isModuleEnabled(moduleId: string): boolean {
    return this.enabledModuleIds().includes(moduleId);
  }

  /** Obtener config de módulo específico */
  getModuleConfig(moduleId: string): ModuleActivationConfig | undefined {
    return this.modulesConfig().find(m => m.moduleId === moduleId);
  }

  // ═══════════════════════════════════════════════════════════════════
  // NUEVOS Signals para páginas dinámicas
  // ═══════════════════════════════════════════════════════════════════

  readonly pagesConfig = computed(() => this.configuration()?.pages ?? []);
  readonly scenarioConfig = computed(() => this.configuration()?.scenario ?? null);
  readonly themeConfig = computed(() => this.configuration()?.theme ?? null);
  readonly generatedFromInfo = computed(() => this.configuration()?.generatedFrom ?? null);
}

Ejemplo: Sistema de Inventario para Restaurante

JSON de Configuración Completo

{
  "version": "1.0.0",
  "generatedAt": "2025-01-15T10:30:00Z",

  "scenario": {
    "id": "restaurant-inventory-v1",
    "name": "Sistema de Inventario para Restaurante",
    "description": "Gestión de inventario y alertas de stock",
    "industry": "restaurant",
    "tags": ["inventory", "food-service"]
  },

  "generatedFrom": {
    "source": "ai",
    "originalPrompt": "Sistema de inventario para restaurante con alertas de stock bajo",
    "generatedAt": "2025-01-15T10:30:00Z"
  },

  "modules": [
    { "moduleId": "inventory", "enabled": true, "config": { "lowStockThreshold": 10 } },
    { "moduleId": "reports", "enabled": true },
    { "moduleId": "user-management", "enabled": false }
  ],

  "navigation": {
    "position": "left",
    "collapsible": true,
    "showBreadcrumbs": true,
    "groups": [
      {
        "id": "main",
        "label": "Principal",
        "order": 1,
        "visible": true,
        "items": [
          {
            "id": "dashboard",
            "label": "Dashboard",
            "icon": "dashboard",
            "route": "/",
            "order": 1,
            "moduleId": "core",
            "visible": true,
            "enabled": true
          },
          {
            "id": "inventory",
            "label": "Inventario",
            "icon": "inventory",
            "route": "/inventory",
            "order": 2,
            "moduleId": "inventory",
            "visible": true,
            "enabled": true
          }
        ]
      }
    ]
  },

  "pages": [
    {
      "id": "dashboard",
      "route": "/",
      "title": "Dashboard de Inventario",
      "icon": "dashboard",
      "layout": { "type": "grid", "columns": 12, "gap": "1rem" },
      "widgets": [
        {
          "id": "low-stock-alerts",
          "widgetTypeId": "alert-list-widget",
          "displayName": "Alertas de Stock Bajo",
          "position": { "x": 0, "y": 0, "width": 6, "height": 2 },
          "enabled": true,
          "bindings": [
            {
              "name": "items",
              "type": "array",
              "required": true,
              "source": "repository",
              "sourceConfig": {
                "type": "repository",
                "entityName": "InventoryItem",
                "method": "findLowStock"
              },
              "reactive": true
            }
          ]
        },
        {
          "id": "stock-value-kpi",
          "widgetTypeId": "kpi-card-widget",
          "displayName": "Valor Total",
          "position": { "x": 6, "y": 0, "width": 3, "height": 1 },
          "enabled": true,
          "bindings": [
            {
              "name": "value",
              "type": "number",
              "source": "repository",
              "sourceConfig": {
                "type": "repository",
                "entityName": "InventoryItem",
                "method": "getTotalValue",
                "valuePath": "total"
              }
            },
            {
              "name": "label",
              "type": "string",
              "source": "manual",
              "sourceConfig": { "type": "manual", "value": "Valor Inventario" }
            }
          ]
        }
      ]
    }
  ],

  "dashboard": {
    "columns": 12,
    "widgets": [],
    "availableWidgets": []
  },

  "topNav": {
    "showTenantSelector": true,
    "showUserMenu": true,
    "showNotifications": true
  },

  "branding": {
    "companyName": "Mi Restaurante",
    "primaryColor": "#2E7D32"
  },

  "theme": {
    "baseTheme": "light",
    "colors": { "primary": "#2E7D32", "secondary": "#FF8F00" }
  }
}

Plan de Implementación

Fase 1: Modelos y Signals

Ubicación: libs/core/module-config/src/lib/

# Tarea Archivo Prioridad
1.1 Crear interfaces AISystemConfiguration, ScenarioConfig, etc. models/ai-system-config.models.ts 🔴 Alta
1.2 Agregar signals de módulos en AppConfigService services/app-config.service.ts 🔴 Alta
1.3 Agregar signals de páginas y tema services/app-config.service.ts 🔴 Alta
1.4 Actualizar barrel exports index.ts 🔴 Alta
1.5 Eliminar AppUiConfiguration models/app-config.models.ts 🟡 Media

Fase 2: Modificar Bootstrap

Ubicación: libs/core/module-integrator/src/lib/bootstrap/

# Tarea Archivo Prioridad
2.1 Remover dependencia de ModuleConfigurationService browser-bootstrapper.service.ts 🔴 Alta
2.2 Usar AppConfigService.enabledModules() browser-bootstrapper.service.ts 🔴 Alta
2.3 Actualizar lógica de filtrado de módulos browser-bootstrapper.service.ts 🔴 Alta

Fase 3: Limpieza de Código Legacy

# Tarea Archivo Prioridad
3.1 Eliminar ModuleConfigurationService module-base/services/ 🔴 Alta
3.2 Eliminar endpoint legacy del mock module-config-mock-api.ts 🔴 Alta
3.3 Actualizar barrel exports de module-base module-base/index.ts 🔴 Alta
3.4 Buscar y eliminar imports huérfanos Proyecto completo 🟡 Media

Fase 4: Componente de Página Dinámica

Ubicación: libs/core/ui-framework/src/lib/dynamic/

# Tarea Archivo Prioridad
4.1 Crear DynamicPageComponent dynamic-page.component.ts 🔴 Alta
4.2 Crear DynamicWidgetHostDirective dynamic-widget-host.directive.ts 🔴 Alta
4.3 Implementar grid layout dinámico Dentro de DynamicPageComponent 🔴 Alta
4.4 Integrar con DataBindingService Resolver bindings 🔴 Alta

Fase 5: Widgets de Demo

Ubicación: libs/core/ui-framework/src/lib/widgets/

# Tarea Archivo Prioridad
5.1 Crear KpiCardWidgetComponent kpi-card-widget.component.ts 🔴 Alta
5.2 Crear AlertListWidgetComponent alert-list-widget.component.ts 🔴 Alta
5.3 Registrar widgets en registry widget-registry.ts 🔴 Alta

Fase 6: Demo End-to-End

Ubicación: apps/gograb-admin/

# Tarea Archivo Prioridad
6.1 Actualizar mock-api con AISystemConfiguration mocks/module-config-mock-api.ts 🔴 Alta
6.2 Crear ruta /ai-demo features/ai-demo/ 🔴 Alta
6.3 Integrar DynamicPageComponent Demo route 🔴 Alta
6.4 Verificar data bindings E2E Testing 🔴 Alta

Diagrama de Flujo Nuevo

┌─────────────────────────────────────────────────────────────────┐
│                     FLUJO DE BOOTSTRAP NUEVO                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. APP_INITIALIZER                                             │
│     └─► BootstrapInitializerService.initializeIfContextExists() │
│                                                                 │
│  2. AppConfigService.loadConfiguration()                        │
│     └─► HTTP GET: /api/config/ui                                │
│         └─► Retorna: AISystemConfiguration (TODO UNIFICADO)     │
│                                                                 │
│  3. BrowserBootstrapperService.initialize()                     │
│     │                                                           │
│     ├─► Lee módulos: AppConfigService.enabledModules()          │
│     │   └─► Signal: ModuleActivationConfig[]                    │
│     │                                                           │
│     ├─► Filtra: modules.filter(m => m.enabled)                  │
│     │                                                           │
│     ├─► ModuleDiscoveryService.discoverAndRegister()            │
│     │                                                           │
│     ├─► ModuleLifecycleService.executeLifecycle()               │
│     │                                                           │
│     └─► RouteRegistrationService.registerModuleRoutes()         │
│                                                                 │
│  4. Componentes consumen signals de AppConfigService            │
│     ├─► SidebarComponent: navigationConfig()                    │
│     ├─► DashboardComponent: dashboardConfig()                   │
│     └─► DynamicPageComponent: pagesConfig()                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Beneficios del Enfoque Directo

Aspecto Antes Después
Servicios de config 2 (ModuleConfigurationService + AppConfigService) 1 (AppConfigService)
Endpoints API 2 (modules + ui config) 1 (/api/config/ui)
Código adapter Necesario para conversión Eliminado
Complejidad Alta (fallbacks, conversiones) Baja (flujo directo)
Mantenimiento Difícil (sincronizar 2 fuentes) Simple (una fuente)
Tipos Múltiples interfaces Una interface unificada

Dependencias Entre Bibliotecas

┌─────────────────────────────────────────────────────────────────┐
│                     GRAFO DE DEPENDENCIAS                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  shared-models ◄─────┬─────────────────────────────────────┐    │
│                      │                                     │    │
│  data-binding ◄──────┼─────────────────────────────────┐   │    │
│       │              │                                 │   │    │
│       ▼              │                                 │   │    │
│  module-config ◄─────┴── (AISystemConfiguration)       │   │    │
│       │                                                │   │    │
│       ▼                                                │   │    │
│  module-integrator ◄───── (usa AppConfigService)       │   │    │
│       │                                                │   │    │
│       ▼                                                │   │    │
│  ui-framework ◄──────────────────────────────────────┬─┘   │    │
│       │              (DynamicPageComponent)          │     │    │
│       │              (Widgets)                       │     │    │
│       ▼                                              │     │    │
│  gograb-admin ◄──────────────────────────────────────┴─────┘    │
│       (Demo route, Mock API)                                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Consideraciones Futuras (Post-PoC)

Reglas Condicionales

Generación IA

Editor Visual

Persistencia


Referencias


Fecha de Creación: 2025-01-15 Última Actualización: 2025-01-15 Estado: Diseño Simplificado - Sin Retrocompatibilidad Próximo Paso: Implementación Fase 1 (Modelos y Signals)