# βœ… SOLUCIΓ“N: Syntaxis como TaskService Integrado **Fecha**: 2025-11-20 **Estado**: Arquitectura correcta basada en patrones existentes **Referencia**: taskservs (databases), provctl (stage1-extended-definitions) --- ## 🎯 El Problema (VersiΓ³n Final) ### ΒΏPor quΓ© Dockerfile o docker-compose NO son suficientes? ``` Dockerfile/docker-compose definen: βœ… CΓ³mo empacar (imagen + dependencias) βœ… QuΓ© puertos exponer βœ… QuΓ© variables de entorno βœ… CΓ³mo iniciar el servicio Pero NO definen: ❌ CΓ³mo GESTIONAR el ciclo de vida (systemd, provctl) ❌ CΓ³mo VALIDAR salud del servicio ❌ CΓ³mo ORQUESTAR mΓΊltiples mΓ‘quinas ❌ CΓ³mo INTEGRAR con provisioning ❌ CΓ³mo ESCALAR en diferentes contextos (local, dev, prod) ❌ Requisitos de INFRA (networking, storage, secrets) ``` ### La SoluciΓ³n: Tres capas coherentes ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CAPA 1: DEFINICIΓ“N (taskserv de syntaxis) β”‚ β”‚ DΓ³nde: /provisioning/extensions/taskservs/development/ β”‚ β”‚ syntaxis/kcl/syntaxis.k β”‚ β”‚ β”‚ β”‚ Define: QuΓ© es syntaxis, sus servicios, requisitos β”‚ β”‚ Lenguaje: KCL (como postgres, redis, kubernetes) β”‚ β”‚ Consumidor: provisioning (como taskserv externo) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CAPA 2: GESTIΓ“N LOCAL (provctl config) β”‚ β”‚ DΓ³nde: /provisioning/extensions/provctl/syntaxis.toml β”‚ β”‚ o generado desde taskserv β”‚ β”‚ β”‚ β”‚ Define: CΓ³mo ejecutar syntaxis localmente (systemd, etc) β”‚ β”‚ Lenguaje: TOML (como minimal-app, containerized-web-app) β”‚ β”‚ Consumidor: provctl (para control local/remoto) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CAPA 3: PRESETS/TEMPLATES (syntaxis installer) β”‚ β”‚ DΓ³nde: syntaxis/configs/deployment-presets.kcl β”‚ β”‚ β”‚ β”‚ Define: QuΓ© servicios en cada contexto (local, dev, prod) β”‚ β”‚ Lenguaje: KCL o YAML (readable, maintainable) β”‚ β”‚ Consumidor: syntaxis installer (para ofrecerpresets) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ INTEGRACIΓ“N: Capa 1 β†’ provisioning la ve como taskserv importable Capa 2 β†’ provctl la puede gestionar localmente Capa 3 β†’ installer ofrece presets (local/dev/prod) ``` --- ## πŸ“ CAPA 1: TaskService en provisioning ### Estructura ``` /Users/Akasha/project-provisioning/provisioning/extensions/taskservs/ └── development/ └── syntaxis/ β”œβ”€β”€ kcl/ β”‚ β”œβ”€β”€ syntaxis.k ← Schema principal β”‚ β”œβ”€β”€ dependencies.k ← Requisitos β”‚ β”œβ”€β”€ kcl.mod ← Module definition β”‚ └── kcl.mod.lock β”œβ”€β”€ default/ β”‚ β”œβ”€β”€ install-syntaxis.sh β”‚ β”œβ”€β”€ env-syntaxis.j2 ← Tera template para vars β”‚ └── config.toml ← Config ejemplo └── README.md ``` ### Archivo: syntaxis.k (Schema) Basado en patrΓ³n real de n8n, pero adaptado a servicios de syntaxis: ```kcl # /provisioning/extensions/taskservs/development/syntaxis/kcl/syntaxis.k # Syntaxis Project Management Platform - Task Service Definition # PatrΓ³n: Similar a n8n, postgres, etc. import regex schema Database: """Database backend configuration for syntaxis""" typ: "sqlite" | "surrealdb" | "postgres" = "sqlite" host?: str = "127.0.0.1:5432" if typ == "postgres" else Undefined port?: int = 5432 if typ == "postgres" else Undefined name: str = "syntaxis" user?: str password?: str path?: str = "/var/lib/syntaxis/syntaxis.db" if typ == "sqlite" else Undefined check: len(name) > 0, "Database name required" typ == "sqlite" or (user != Undefined and len(user) > 0), "User required for postgres/surrealdb" schema Service: """Individual service configuration within syntaxis""" name: str type: "binary" | "service" | "web" enabled: bool = False port?: int protocol?: str = "http" check: len(name) > 0, "Service name required" schema Syntaxis: """ Syntaxis Project Management Platform Pattern: Like n8n, but for project management """ # Identity name: str = "syntaxis" version: str app_name: str = "syntaxis Project Manager" # System paths work_path: str = "/var/lib/syntaxis" etc_path: str = "/etc/syntaxis" log_path: str = "/var/log/syntaxis" bin_path: str = "/usr/local/bin/syntaxis" # HTTP/Network Configuration protocol: "http" | "https" = "http" http_addr: str = "127.0.0.1" http_port: int = 3000 domain: str = "localhost" # Services (CLI, TUI, API, Dashboard) cli: Service = { name = "syntaxis-cli" type = "binary" enabled = True } tui: Service = { name = "syntaxis-tui" type = "binary" enabled = False } api: Service = { name = "syntaxis-api" type = "service" enabled = False port = 3000 protocol = "http" } dashboard: Service = { name = "syntaxis-dashboard" type = "web" enabled = False port = 8080 protocol = "http" } # Database configuration db: Database = {typ = "sqlite"} # Dependencies (other taskservs) dependencies: [str] = [] # e.g., ["surrealdb", "nats"] # Application settings timezone: str = "UTC" language: str = "en" log_level: "debug" | "info" | "warn" | "error" = "info" # Validation check: len(domain) > 0, "domain is required" 1 <= http_port <= 65535, "http_port must be between 1 and 65535" regex.match(domain, r"^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$"), "Invalid domain format" # Extended configurations for different modes schema Syntaxis_Dev(Syntaxis): """Development configuration""" protocol = "http" http_addr = "127.0.0.1" http_port = 3000 api.enabled = True dashboard.enabled = True tui.enabled = True db = { typ = "sqlite" path = "/var/lib/syntaxis/syntaxis-dev.db" } dependencies = ["surrealdb"] schema Syntaxis_Production(Syntaxis): """Production HA configuration""" protocol = "https" http_addr = "0.0.0.0" http_port = 3000 api.enabled = True dashboard.enabled = False # No dashboard in prod cli.enabled = True db = { typ = "postgres" host = "localhost:5432" name = "syntaxis_prod" user = "syntaxis" } dependencies = ["postgres", "nats"] check: protocol == "https", "Production must use HTTPS" db.typ == "postgres", "Production must use PostgreSQL" ``` ### Archivo: dependencies.k (Requisitos) ```kcl # /provisioning/extensions/taskservs/development/syntaxis/kcl/dependencies.k schema SyntaxisRequirements: """System and service requirements for syntaxis""" system: min_memory_gb: int = 2 min_disk_gb: int = 5 min_cpu_cores: int = 1 # Optional external services optional_services: [str] = [ "surrealdb", # For persistence "nats", # For messaging ] ports: api: int = 3000 dashboard: int = 8080 check: min_memory_gb > 0, "Min memory must be > 0" min_disk_gb > 0, "Min disk must be > 0" ``` ### Uso en provisioning ```kcl # En /provisioning/kcl/services.k o similar import syntaxis_module = .extensions.taskservs.development.syntaxis syntaxis_service: syntaxis_module.Syntaxis = { name = "syntaxis" version = "0.1.0" deployment_mode = "prod" cli.enabled = True api.enabled = True dashboard.enabled = True database.enabled = True database.type = "postgres" # Use provisioned postgres dependencies = ["postgres"] # Require postgres taskserv } ``` --- ## πŸ”§ CAPA 2: GestiΓ³n Local con provctl ### Estructura ``` /Users/Akasha/Development/provctl/ β”œβ”€β”€ examples/ β”‚ └── stage1-extended-definitions/ β”‚ └── syntaxis-local-dev.toml ← NEW: Syntaxis config β”œβ”€β”€ provisioning/ β”‚ └── extensions/ β”‚ └── syntaxis/ β”‚ └── syntaxis.toml ← NEW: provctl-friendly config ``` ### Archivo: syntaxis-local-dev.toml (provctl config) ```toml # /provctl/examples/stage1-extended-definitions/syntaxis-local-dev.toml # Syntaxis local development configuration for provctl [metadata] name = "syntaxis-local-dev" description = "Syntaxis local development with all services" version = "0.1.0" # Main API service [service] name = "syntaxis-api" binary = "/usr/local/bin/syntaxis-api" args = ["--bind", "127.0.0.1:3000"] working_dir = "/opt/syntaxis" [service.env_vars] RUST_LOG = "debug" DATABASE_URL = "sqlite:///var/lib/syntaxis/syntaxis.db" ENVIRONMENT = "development" # Optional: TUI service [[services]] name = "syntaxis-tui" binary = "/usr/local/bin/syntaxis-tui" enabled = false # Off by default # Optional: Dashboard service [[services]] name = "syntaxis-dashboard" type = "web" port = 8080 enabled = false # Health check for API [[health_checks]] name = "api-health" type = "http" endpoint = "http://127.0.0.1:3000/health" interval_seconds = 10 timeout_seconds = 5 [[health_checks]] name = "api-ready" type = "http" endpoint = "http://127.0.0.1:3000/api/projects" interval_seconds = 30 timeout_seconds = 10 required = false # Optional endpoint # Secrets management [[secrets]] name = "db-password" backend = "file" path = "/var/lib/syntaxis/.db-password" env_var = "DATABASE_PASSWORD" # Container variant (optional) [container] image = "syntaxis:latest" registry = "docker.io" image_pull_policy = "IfNotPresent" [container.env_vars] RUST_LOG = "debug" # Database setup [[data_services]] name = "sqlite" type = "sqlite" version = "3" path = "/var/lib/syntaxis/syntaxis.db" auto_migrate = true ``` ### CΓ³mo provctl lo consumirΓ­a ```bash # Developer corre provctl config apply --from-file /provctl/examples/syntaxis-local-dev.toml # O desde taskserv (si se integra) provctl config apply --from-taskserv syntaxis --mode dev # Resultado: # - Crea configuraciΓ³n local # - Inicia servicios con systemd/launchd # - Monitorea health # - Proporciona CLI para control ``` --- ## 🎯 CAPA 3: Presets en syntaxis ### Estructura ``` syntaxis/ β”œβ”€β”€ configs/ β”‚ β”œβ”€β”€ deployment-presets.kcl ← NEW: Define presets β”‚ β”œβ”€β”€ services-catalog.toml ← EXISTENTE (documentaciΓ³n) β”‚ └── database.toml └── src/ ``` ### Archivo: deployment-presets.kcl ```kcl # syntaxis/configs/deployment-presets.kcl # Deployment presets for different contexts schema DeploymentPreset: """A deployment preset for syntaxis""" name: str description: str services: {str: bool} # service_id: enabled manager: str # "manual", "systemd", "provctl", "provisioning" requirements: [str] # taskservs needed (e.g., ["surrealdb"]) preset_local: DeploymentPreset = { name = "local" description = "Single machine, CLI only. No services. Manual everything." services = { "cli": True, "tui": False, "api": False, "dashboard": False, } manager = "manual" requirements = [] } preset_dev: DeploymentPreset = { name = "dev" description = "Local development with full stack (CLI, API, Dashboard, DB)" services = { "cli": True, "tui": True, "api": True, "dashboard": True, } manager = "provctl" # provctl manages locally requirements = ["surrealdb"] # Need database } preset_staging: DeploymentPreset = { name = "staging" description = "Staging environment (multiple machines, HA)" services = { "cli": True, "api": True, "dashboard": True, } manager = "provisioning" # Full provisioning management requirements = ["postgres", "nats", "kubernetes"] } preset_production: DeploymentPreset = { name = "production" description = "Production deployment (HA, multi-region, monitoring)" services = { "api": True, "dashboard": False, # No dashboard in prod } manager = "provisioning" # Full provisioning + monitoring requirements = ["postgres", "nats", "kubernetes", "prometheus"] } all_presets = [ preset_local, preset_dev, preset_staging, preset_production, ] ``` ### Uso: syntaxis installer ```rust // syntaxis/core/crates/cli/src/installer.rs pub fn list_presets() -> Vec { // Load from configs/deployment-presets.kcl KCL::load("configs/deployment-presets.kcl") .all_presets } pub fn install(preset: &str) -> Result<()> { let preset_config = load_preset(preset)?; println!("πŸ“¦ Installing preset: {}", preset_config.name); println!(" {}", preset_config.description); println!(" Services: {:?}", preset_config.services); println!(" Manager: {}", preset_config.manager); match preset_config.manager { "manual" => { println!("Manual setup. Follow these steps:"); print_manual_guide(&preset_config); } "provctl" => { if detect_provctl()? { println!("provctl detected. Configuring..."); apply_provctl_config(&preset_config)?; } else { println!("provctl not found. Install from: https://..."); } } "provisioning" => { println!("Provisioning required. Integrating..."); integrate_with_provisioning(&preset_config)?; } _ => {} } Ok(()) } ``` ### Resultado: Coherencia entre capas ``` syntaxis installer ↓ Lee: deployment-presets.kcl β”œβ”€ "local" β†’ manual setup β”œβ”€ "dev" β†’ provctl (if available) β”œβ”€ "staging" β†’ provisioning └─ "production" β†’ provisioning + monitoring ↓ Para cada preset: β”œβ”€ Lee requisitos (surrealdb, nats, etc) β”œβ”€ Genera config provctl (si manager="provctl") β”œβ”€ O integra con provisioning (si manager="provisioning") └─ Ofrece comandos para cada paso ``` --- ## πŸ”— CΓ³mo Se Conectan Las Tres Capas ### CAPA 1: DefiniciΓ³n en provisioning ```kcl # provisioning/extensions/taskservs/development/syntaxis/kcl/syntaxis.k schema Syntaxis: version: str deployment_mode: str database: { type: str, ... } health_checks: { ... } ``` ### CAPA 2: ConfiguraciΓ³n en provctl ```toml # provctl/examples/syntaxis-local-dev.toml [service] name = "syntaxis-api" binary = "/usr/local/bin/syntaxis-api" args = ["--bind", "127.0.0.1:3000"] [[health_checks]] type = "http" endpoint = "http://127.0.0.1:3000/health" ``` ### CAPA 3: Presets en syntaxis ```kcl # syntaxis/configs/deployment-presets.kcl preset_dev: DeploymentPreset = { manager = "provctl" requirements = ["surrealdb"] services = { "api": True, "tui": True, ... } } ``` ### Flujo de integraciΓ³n ``` Developer usa syntaxis installer: ↓ installer lee deployment-presets.kcl ↓ Elige preset "dev": β”œβ”€ manager = "provctl" β†’ installer llama provctl β”œβ”€ requirements = ["surrealdb"] β†’ verificar disponible └─ services = { "api": True, ... } β†’ generar config ↓ provctl aplica config (desde syntaxis-local-dev.toml) β”œβ”€ Genera config systemd/launchd β”œβ”€ Inicia servicios β”œβ”€ Monitorea health └─ Proporciona CLI para control ↓ Si necesita provisioning (preset "prod"): β”œβ”€ installer detecta provisioning β”œβ”€ syntaxis se importa como taskserv β”œβ”€ provisioning ve requisitos (postgres, nats, etc) β”œβ”€ provisioning orchestra todo └─ Resultado: Full stack en producciΓ³n ``` --- ## πŸ“Š ComparaciΓ³n: Antes vs DespuΓ©s | Aspecto | TOML Compilado | SoluciΓ³n (3 Capas) | |---------|---|---| | **DefiniciΓ³n** | TOML β†’ catalog.rs β†’ ingestionable | KCL taskserv (como postgres) | | **GestiΓ³n local** | ΒΏCΓ³mo ejecutar? | provctl TOML config (como minimal-app) | | **Presets** | No existen | KCL en syntaxis (deployment-presets.kcl) | | **Cambios requieren** | RecompilaciΓ³n | Solo guardar archivo | | **Consumible por** | provisioning tools | provisioning, provctl, installer | | **Escalabilidad** | Acoplado a Rust | Modular, extensible | | **Developer experience** | "ΒΏQuΓ© es este TOML?" | "Elige preset: local, dev, staging, prod" | --- ## βœ… Beneficios ### Para Developer ``` βœ… Elige preset (local, dev, staging, prod) βœ… Instalador automΓ‘tico lo detecta todo βœ… Corre syntaxis: local manual, dev con provctl, prod con provisioning βœ… NO ve TOML compilado, ve presets legibles ``` ### Para provisioning ``` βœ… syntaxis es un taskserv como cualquier otro (postgres, kubernetes, etc) βœ… Lo importa como dependency externo βœ… Lo orquesta en contexto de infra βœ… Sabe requisitos (quΓ© bases de datos, etc) del schema KCL ``` ### Para provctl ``` βœ… Lee config TOML como cualquier otro servicio βœ… Puede gestionar syntaxis localmente βœ… Puede gestionar sintaxis remotamente (SSH) βœ… Health checks automΓ‘ticos ``` ### Para installer ``` βœ… Ofrece presets claros βœ… DetecciΓ³n inteligente (provisioning? provctl? manual?) βœ… Configura automΓ‘ticamente βœ… Fallback gracioso con guΓ­a manual ``` --- ## πŸš€ ImplementaciΓ³n (Roadmap MΓ­nimo) ### Paso 1: Crear taskserv en provisioning ``` 1. Crear estructura: provisioning/extensions/taskservs/development/syntaxis/ 2. Definir KCL: - syntaxis.k (schema principal) - dependencies.k (requisitos) 3. Agregar ejemplos: - install-syntaxis.sh - env-syntaxis.j2 ``` ### Paso 2: Crear config provctl ``` 1. Crear: provctl/examples/syntaxis-local-dev.toml 2. Define: - Service principal (syntaxis-api) - Health checks - Variables de entorno - Secretos ``` ### Paso 3: Crear presets en syntaxis ``` 1. Crear: syntaxis/configs/deployment-presets.kcl 2. Define: - preset_local - preset_dev - preset_staging - preset_production ``` ### Paso 4: Integrar con installer ``` 1. Extender syntaxis installer para: - Leer presets - Detectar provctl/provisioning - Aplicar configuraciΓ³n automΓ‘tica ``` --- ## πŸ“Œ Resumen **El problema**: TOML compilado es ingestionable, requiere recompilaciΓ³n, no es escalable. **La soluciΓ³n**: Tres capas coherentes: 1. **CAPA 1 (provisioning)**: TaskService KCL (como postgres) 2. **CAPA 2 (provctl)**: Config TOML (como minimal-app) 3. **CAPA 3 (syntaxis)**: Presets KCL (local/dev/staging/prod) **Resultado**: - Developer elige preset - Installer detecta contexto - Se configura automΓ‘ticamente - Funciona sin Docker/compose requirements adicionales - Integrable con provisioning y provctl **Por quΓ© funciona**: - Sigue patrones EXISTENTES en provisioning y provctl - No inventa nuevos formatos - Reutiliza cΓ³digo/infraestructura existente - Escalable a otros proyectos (como "taskservs externo")