# SERVICE DESCRIPTOR STANDARD **Version:** 1.0.0 **Fecha:** 2025-12-18 **Sistema:** SIMCO v2 - Workspace v1 **Tipo:** Estandar de Contrato de Servicio --- ## PROPOSITO El Service Descriptor es un **contrato universal** que define completamente un servicio, conectando: - Codigo fuente con registries - Agentes con responsabilidades - CI/CD con configuracion - Monitoreo con endpoints **Principio:** Los agentes dejan de "inferir" y empiezan a "leer contrato". --- ## UBICACION Cada servicio debe tener un archivo `service.descriptor.yml` en su raiz: ``` gamilit-platform/ +-- apps/ | +-- backend/ | | +-- service.descriptor.yml # <- Descriptor del backend | | +-- src/ | | +-- package.json | +-- frontend/ | +-- service.descriptor.yml # <- Descriptor del frontend | +-- src/ | +-- package.json +-- docker/ +-- orchestration/ ``` --- ## SCHEMA COMPLETO ```yaml # ============================================================================== # SERVICE DESCRIPTOR - Schema v1.0.0 # ============================================================================== # Este archivo define completamente un servicio # OBLIGATORIO en la raiz de cada servicio # ============================================================================== # ------------------------------------------------------------------------------ # IDENTIFICACION DEL SERVICIO # ------------------------------------------------------------------------------ service: # Nombre unico del servicio (kebab-case) name: "string" # Ej: "gamilit-api", "erp-frontend" # Tipo de servicio type: "backend | frontend | database | ml | worker | gateway" # Runtime/tecnologia runtime: "node | python | go | java | static | postgres" # Version del servicio (semver) version: "string" # Ej: "1.0.0" # Descripcion breve description: "string" # Agente responsable (para SIMCO) owner_agent: "NEXUS-BACKEND | NEXUS-FRONTEND | NEXUS-DATABASE | NEXUS-ML" # ------------------------------------------------------------------------------ # REPOSITORIO # ------------------------------------------------------------------------------ repository: # Nombre del repo name: "string" # Ej: "gamilit-platform" # Ruta relativa al servicio dentro del repo path: "string" # Ej: "apps/backend" # Branch principal main_branch: "main | master" # ------------------------------------------------------------------------------ # PUERTOS (referencia a ports.registry.yml) # ------------------------------------------------------------------------------ ports: # Puerto interno del servicio internal: number # Ej: 3000 # Referencia al registry (para validacion) registry_ref: "string" # Ej: "projects.gamilit.api" # Protocolo protocol: "http | https | ws | wss | grpc" # ------------------------------------------------------------------------------ # DOMINIOS (referencia a domains.registry.yml) # ------------------------------------------------------------------------------ domains: # Referencia al proyecto en domains.registry registry_ref: "string" # Ej: "gamilit" # Override por ambiente (opcional) overrides: local: "string" # Ej: "localhost:3000" development: "string" staging: "string" production: "string" # ------------------------------------------------------------------------------ # BASE DE DATOS (referencia a databases.registry.yml) # ------------------------------------------------------------------------------ database: # Referencia al proyecto en databases.registry registry_ref: "string" # Ej: "gamilit" # Rol a usar (del registry) role: "runtime | migrator | owner" # Schemas que usa este servicio schemas: - "string" # Ej: ["public", "auth"] # ------------------------------------------------------------------------------ # AMBIENTES # ------------------------------------------------------------------------------ environments: # Lista de ambientes donde despliega deployed_to: - "local" - "development" - "staging" - "production" # Ambiente por defecto para desarrollo default: "local" # ------------------------------------------------------------------------------ # HEALTH CHECK # ------------------------------------------------------------------------------ healthcheck: # Path del endpoint de health path: "string" # Ej: "/health" # Intervalo de verificacion interval: "string" # Ej: "30s" # Timeout timeout: "string" # Ej: "5s" # Reintentos antes de marcar unhealthy retries: number # Ej: 3 # ------------------------------------------------------------------------------ # DEPENDENCIAS # ------------------------------------------------------------------------------ dependencies: # Otros servicios de los que depende services: - name: "string" required: boolean healthcheck: "string" # URL del healthcheck # Bases de datos databases: - "string" # Nombres de BD del registry # Servicios externos external: - name: "string" url: "string" required: boolean # ------------------------------------------------------------------------------ # CI/CD # ------------------------------------------------------------------------------ ci: # Nombre del pipeline a usar pipeline: "string" # Ej: "node-backend-standard" # Flags de CI tests: boolean lint: boolean build: boolean docker: boolean # Imagen Docker (si aplica) docker_image: "string" # Ej: "gamilit-api:latest" # Registry de Docker docker_registry: "string" # Ej: "ghcr.io/tu-org" # ------------------------------------------------------------------------------ # OBSERVABILIDAD # ------------------------------------------------------------------------------ observability: # Metricas metrics: enabled: boolean path: "string" # Ej: "/metrics" port: number # Ej: 9090 # Logging logging: level: "debug | info | warn | error" format: "json | text" # Tracing tracing: enabled: boolean provider: "string" # Ej: "jaeger", "zipkin" # ------------------------------------------------------------------------------ # RECURSOS (para Kubernetes/Docker) # ------------------------------------------------------------------------------ resources: # Limites de CPU cpu: request: "string" # Ej: "100m" limit: "string" # Ej: "500m" # Limites de memoria memory: request: "string" # Ej: "128Mi" limit: "string" # Ej: "512Mi" # Replicas replicas: min: number max: number # ------------------------------------------------------------------------------ # METADATA # ------------------------------------------------------------------------------ metadata: # Fecha de creacion created: "string" # ISO date # Ultima actualizacion updated: "string" # ISO date # Mantenedores maintainers: - name: "string" email: "string" # Tags para busqueda tags: - "string" # Links relacionados links: documentation: "string" repository: "string" monitoring: "string" ``` --- ## EJEMPLOS ### Backend NestJS ```yaml # gamilit-platform/apps/backend/service.descriptor.yml service: name: "gamilit-api" type: "backend" runtime: "node" version: "1.0.0" description: "API principal de Gamilit - Plataforma de gamificacion educativa" owner_agent: "NEXUS-BACKEND" repository: name: "gamilit-platform" path: "apps/backend" main_branch: "main" ports: internal: 3000 registry_ref: "projects.gamilit.api" protocol: "http" domains: registry_ref: "gamilit" overrides: local: "localhost:3000" database: registry_ref: "gamilit" role: "runtime" schemas: - "public" - "auth" - "gamification" - "progress_tracking" environments: deployed_to: - "local" - "development" - "production" default: "local" healthcheck: path: "/health" interval: "30s" timeout: "5s" retries: 3 dependencies: services: [] databases: - "gamilit_db" external: - name: "stripe" url: "https://api.stripe.com" required: false ci: pipeline: "node-backend-standard" tests: true lint: true build: true docker: true docker_image: "gamilit-api" docker_registry: "ghcr.io/tu-org" observability: metrics: enabled: true path: "/metrics" port: 9090 logging: level: "info" format: "json" tracing: enabled: false resources: cpu: request: "100m" limit: "500m" memory: request: "256Mi" limit: "512Mi" replicas: min: 1 max: 3 metadata: created: "2025-01-01" updated: "2025-12-18" maintainers: - name: "Tech Team" email: "tech@ejemplo.com" tags: - "api" - "nestjs" - "gamification" links: documentation: "/docs" repository: "https://github.com/tu-org/gamilit-platform" ``` ### Frontend React ```yaml # gamilit-platform/apps/frontend/service.descriptor.yml service: name: "gamilit-web" type: "frontend" runtime: "static" version: "1.0.0" description: "Frontend web de Gamilit" owner_agent: "NEXUS-FRONTEND" repository: name: "gamilit-platform" path: "apps/frontend" main_branch: "main" ports: internal: 3001 registry_ref: "projects.gamilit.web" protocol: "http" domains: registry_ref: "gamilit" overrides: local: "localhost:3001" database: registry_ref: null # Frontend no accede directo a BD environments: deployed_to: - "local" - "development" - "production" default: "local" healthcheck: path: "/" interval: "60s" dependencies: services: - name: "gamilit-api" required: true healthcheck: "http://gamilit-api:3000/health" databases: [] external: [] ci: pipeline: "react-frontend-standard" tests: true lint: true build: true docker: true docker_image: "gamilit-web" metadata: created: "2025-01-01" updated: "2025-12-18" tags: - "frontend" - "react" - "web" ``` --- ## USO POR AGENTES ### Backend-Agent ```yaml # En PERFIL-BACKEND.md, agregar: PASO_NUEVO_SERVICE_DESCRIPTOR: al_crear_servicio: - Crear service.descriptor.yml en raiz del servicio - Verificar que ports.registry_ref existe en ports.registry.yml - Verificar que database.registry_ref existe en databases.registry.yml - Completar todos los campos obligatorios al_modificar_servicio: - Actualizar version en service.descriptor.yml - Actualizar metadata.updated - Si cambian puertos: actualizar ports.registry.yml PRIMERO ``` ### DevOps-Agent ```yaml # En PERFIL-DEVOPS.md: VALIDACION_SERVICE_DESCRIPTOR: pre_deploy: - Leer service.descriptor.yml - Validar ports.registry_ref existe - Validar domains.registry_ref existe - Validar database.registry_ref existe - Ejecutar healthcheck.path ci_pipeline: - Usar ci.pipeline para seleccionar template - Ejecutar ci.tests, ci.lint, ci.build segun flags - Construir ci.docker_image si docker: true ``` --- ## VALIDACION ### Script: validate-service-descriptor.sh ```bash #!/bin/bash # Valida que un service.descriptor.yml sea correcto DESCRIPTOR="$1" if [ ! -f "$DESCRIPTOR" ]; then echo "ERROR: Descriptor no encontrado: $DESCRIPTOR" exit 1 fi # Validar YAML python3 -c "import yaml; yaml.safe_load(open('$DESCRIPTOR'))" || exit 1 # Validar campos obligatorios python3 << EOF import yaml import sys with open('$DESCRIPTOR', 'r') as f: d = yaml.safe_load(f) required = ['service', 'repository', 'ports', 'environments', 'ci'] for field in required: if field not in d: print(f"ERROR: Campo obligatorio faltante: {field}") sys.exit(1) # Validar service for field in ['name', 'type', 'runtime', 'owner_agent']: if field not in d['service']: print(f"ERROR: service.{field} es obligatorio") sys.exit(1) print("OK: Descriptor valido") EOF ``` --- ## INTEGRACION CON SIMCO ### SIMCO-SERVICE-DESCRIPTOR.md (Nueva directiva) ```markdown # SIMCO: SERVICE DESCRIPTOR ## REGLA FUNDAMENTAL Todo servicio DEBE tener un service.descriptor.yml en su raiz. El descriptor es la fuente de verdad para: - Configuracion de puertos - Configuracion de dominios - Configuracion de BD - Pipelines de CI/CD ## CUANDO CREAR 1. Al crear un nuevo servicio 2. Al migrar un servicio existente al workspace v1 ## COMO CREAR 1. Copiar SERVICE-DESCRIPTOR-TEMPLATE.yml 2. Completar todos los campos 3. Verificar referencias a registries 4. Validar con validate-service-descriptor.sh ## CUANDO ACTUALIZAR 1. Cambio de puerto -> Actualizar ports + registry 2. Cambio de BD -> Actualizar database + registry 3. Nueva dependencia -> Actualizar dependencies 4. Cualquier cambio -> Actualizar metadata.updated ``` --- **Documento generado por:** Architecture-Analyst **Version:** 1.0.0