Files
OmniRoute/docs/i18n/es/CONTRIBUTING.md
Diego Rodrigues de Sa e Souza b637350680 fix(docs): re-sync the 65 documentation mirror sets; section-level docs pipeline; drift gate blocking (#13940)
1,104 mirrors rewritten over five passes of run-translation on the 22-source core set: the 14 sources edited since their translation, the 322 mirrors that were still English copies, and the frontmatter the old extractor leaked into the newer locales' bodies. The pipeline now caches per-`## `-section hashes and retranslates only changed sections, never reuses a section that is still English, rebuilds English-copy / leaked mirrors even when the source is unchanged, merges the state on save (parallel runs), and the drift gate (scoped to the core set) is blocking. Final audit: 0 stale, 0 English copies, 0 leaked frontmatter across 1,430 core mirrors.

⚠️ base-red inherited: #12732
2026-09-17 02:55:31 -03:00

25 KiB

Contributing to OmniRoute (Español)

🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW


Thank you for your interest in contributing! This guide covers everything you need to get started.


Configuración del entorno de desarrollo

Requisitos previos

  • Node.js >=22.22.3 <23, o >=24.0.0 <27 (recomendado: 24 LTS)
  • npm 10+

Usuarios de npm v11+ (Node 24+): Después de ejecutar npm install, verifica que se hayan instalado los módulos nativos: node -e "require('better-sqlite3')". Si falla con MODULE_NOT_FOUND, ejecuta npm approve-scripts better-sqlite3 && npm install. Consulta Solución de problemas.

  • Git

Clonación e instalación

git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
npm install

Variables de entorno

# Crea tu archivo .env a partir de la plantilla
cp .env.example .env

# Genera los secretos necesarios
echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env

Variables clave para el desarrollo:

Variable Valor predeterminado de desarrollo Descripción
PORT 20128 Puerto del servidor
NEXT_PUBLIC_BASE_URL http://localhost:20128 URL base para el frontend
JWT_SECRET (generar arriba) Secreto para firmar los JWT
INITIAL_PASSWORD CHANGEME Contraseña del primer inicio de sesión
APP_LOG_LEVEL info Nivel de detalle de los registros

Configuración del panel

El panel proporciona controles de interfaz para funciones que también pueden configurarse mediante variables de entorno:

Ubicación de la configuración Control Descripción
Configuración → Avanzado Modo de depuración Habilita los registros de solicitudes de depuración (interfaz)
Configuración → General Visibilidad de la barra lateral Muestra/oculta secciones de la barra lateral

Esta configuración se almacena en la base de datos y persiste entre reinicios; cuando se establece, prevalece sobre los valores predeterminados de las variables de entorno.

Ejecución local

# Modo de desarrollo (recarga automática)
npm run dev

# Compilación de producción
npm run build    # next build → .build/next/ y luego assembleStandalone → dist/
npm run start

# Compilación rápida solo del backend/API para cambios de colaboradores
npm run build:contributor

# Compilación de lanzamiento (recompilación limpia + centinela HEAD — obligatoria para el despliegue)
npm run build:release   # rm -rf .build dist && build + escribe dist/BUILD_SHA

# Configuración común del puerto
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev

La compilación para colaboradores realiza una validación únicamente mediante compilación: no ensambla la distribución independiente ni compila los recursos opcionales del empaquetado nativo. Usa la compilación normal de producción cuando necesites validar el paquete distribuible.

Estructura de la salida de compilación

Directorio Contenido Con seguimiento
src/ Código fuente de la aplicación (TypeScript / TSX)
.build/ Archivos intermedios — salida de next build (ignorada por git, distDir = .build/next) No
dist/ Paquete distribuible — ensamblado por assembleStandalone (ignorado por git) No

El proceso de compilación se realiza en una sola pasada:

npm run build
  └─ next build → .build/next/standalone  (salida de Next.js)
  └─ assembleStandalone()                 (copia los archivos independientes + estáticos + públicos + recursos nativos)
       └─ salida: dist/                   (server.js, .next/static/, public/, node_modules/)

npm run build:release también limpia primero ambos directorios y escribe dist/BUILD_SHA (= git rev-parse --short HEAD) como centinela de integridad del despliegue.

npm run build:contributor usa el perfil de compilación exclusivo para el backend. Sustituye temporalmente por archivos provisionales los archivos de la interfaz del panel durante la compilación, conserva los controladores de rutas de la API y restaura los archivos originales después de la compilación. Usa npm run build para los cambios que afecten a la interfaz del panel o para realizar una validación completa del lanzamiento; el perfil para colaboradores no sustituye la compilación de lanzamiento.

Nota sobre el despliegue en VPS: el directorio remoto de la imagen /usr/lib/node_modules/omniroute/app/ no cambia. Las herramientas de despliegue sincronizan mediante rsync el contenido de dist/ en él. Solo cambió la ruta de salida de compilación dentro del repositorio (app/dist/).

URL predeterminadas:

  • Panel: http://localhost:20128/dashboard
  • API: http://localhost:20128/v1

Flujo de trabajo de Git

⚠️ NUNCA hagas commits directamente en main. Usa siempre ramas de funcionalidades.

Base del PR: selecciona como destino la rama release/vX.Y.Z activa (no main). Consulta docs/ops/BRANCHING_MODEL.md para conocer el modelo de una rama por versión y etiquetado al publicar.

# Crea una rama desde el extremo de la versión activa (ejemplo: release/v3.8.49)
git fetch origin
git checkout -b feat/your-feature-name origin/release/v3.8.49
# ... realiza los cambios ...
git commit -m "feat: describe your change"
git push -u origin feat/your-feature-name
# Abre una solicitud de incorporación de cambios con base = release/v3.8.49

Nomenclatura de ramas

Prefijo Propósito
feat/ Nuevas funcionalidades
fix/ Correcciones de errores
refactor/ Reestructuración del código
docs/ Cambios en la documentación
test/ Adiciones/correcciones de pruebas
chore/ Herramientas, CI, dependencias

Mensajes de commit

Sigue Conventional Commits:

feat: add circuit breaker for provider calls
fix: resolve JWT secret validation edge case
docs: update SECURITY.md with PII protection
test: add observability unit tests
refactor(db): consolidate rate limit tables

Ámbitos (v3.8): db, sse, oauth, dashboard, api, cli, docker, ci, mcp, a2a, memory, skills, cloud-agent, guardrails, compression, auto-combo, resilience, providers, executors, translator, domain, authz.


Ejecución de pruebas

# Todas las pruebas (unitarias + vitest + ecosistema + e2e)
npm run test:all

# Un solo archivo de pruebas (ejecutor de pruebas nativo de Node.js; la mayoría de las pruebas usan este)
node --import tsx/esm --test tests/unit/your-file.test.ts

# Solo las pruebas unitarias afectadas por tu cambio (el mismo selector TIA que en la comprobación de CI, #8084)
npm run test:scoped            # cambios en el último commit (o en el árbol de trabajo)
npm run test:scoped:staged     # solo cambios en staging; combina bien con una ejecución previa al commit
npm run test:scoped:full       # primero reconstruye el mapa del grafo de importaciones (tras añadir/mover archivos)
# El código de salida 1 + «ejecuta la suite completa» significa que ha cambiado un archivo central (tsconfig, package.json, …) o
# un archivo fuente no mapeado; el selector falla de forma segura, nunca omite pruebas silenciosamente.

# Vitest (servidor MCP, autoCombo, caché)
npm run test:vitest

# Pruebas E2E (requieren Playwright)
npm run test:e2e

# Pruebas E2E de clientes de protocolo (transportes MCP, A2A)
npm run test:protocols:e2e

# Pruebas de compatibilidad del ecosistema
npm run test:ecosystem

# Umbral de cobertura: 60 % de sentencias/líneas/funciones/ramas
npm run test:coverage
npm run coverage:report

# Comprobación de lint y formato
npm run lint
npm run check

# Prueba de humo combinada y controlada con servicios upstream reales (requiere acceso al VPS y créditos reales del proveedor)
# Accede a proveedores REALES; tiene un pequeño coste. NUNCA se ejecuta en CI. Se omite correctamente sin la activación.
# Requiere: acceso mediante ssh root@192.168.0.15 (obtiene del VPS una instantánea de la base de datos de solo lectura).
RUN_COMBO_LIVE=1 npm run test:combo:live

# Prueba de humo en vivo del VPS de la fase 3: scripts ESM de Node sin formato adicional que acceden directamente al servidor .15 en vivo.
# Requiere: acceso mediante ssh root@192.168.0.15 (los combos se crean/eliminan mediante SQLite por SSH).
# Accede a proveedores REALES (coste reducido). Crea/elimina únicamente combos __live_test__*. NUNCA se ejecuta en CI.
# REQUIRE_API_KEY=false en .15, por lo que no se necesita ninguna clave de API, pero respeta COMBO_LIVE_BASE_URL / COMBO_LIVE_API_KEY si están definidos.
npm run test:combo:live:vps              # 7 escenarios HTTP (prioridad/round-robin/ponderado/coste/fusión/automático + estado)
npm run test:combo:live:vps:failover     # añade un escenario real de conmutación por error entre proveedores (8 en total)

Notas sobre la cobertura:

  • npm run test:coverage mide la cobertura del código fuente para la suite principal de pruebas unitarias, excluye tests/** e incluye open-sse/**
  • Las solicitudes de incorporación de cambios deben mantener el umbral de cobertura en 60 % o más de sentencias/líneas/funciones/ramas
  • Si un PR cambia código de producción en src/, open-sse/, electron/ o bin/, debe añadir o actualizar pruebas automatizadas en el mismo PR
  • npm run coverage:report muestra el informe detallado archivo por archivo de la última ejecución de cobertura
  • npm run test:coverage:legacy conserva la métrica anterior para realizar comparaciones históricas
  • Consulta docs/ops/COVERAGE_PLAN.md para ver la hoja de ruta por fases destinada a mejorar la cobertura

Requisitos de las solicitudes de incorporación de cambios

Antes de abrir un PR, usa la Ruta recomendada para contribuir para ejecutar el ciclo específico correspondiente a lo que hayas cambiado. La suite unitaria completa (4 particiones de CI), Vitest, el umbral de cobertura de 60 % o más y la compilación de producción son responsabilidad de CI; ejecutarlos localmente no aporta ninguna señal que las comprobaciones del PR no vayan a proporcionar ya y, en máquinas más pequeñas, puede saturar el host (#8084):

  • Ejecuta los archivos de pruebas que cubren tu cambio: node --import tsx/esm --test tests/unit/<file>.test.ts
  • Ejecuta npm run lint
  • Incluye o actualiza pruebas automatizadas en el mismo PR siempre que cambie el código de producción
  • Incluye en la descripción del PR los archivos de pruebas modificados o añadidos cuando haya cambiado el código de producción
  • Comprueba el resultado de SonarQube en el PR cuando los secretos del proyecto estén configurados en CI

Estado actual de las pruebas: 122 archivos de pruebas unitarias que cubren:

  • Traductores de proveedores y conversión de formatos
  • Limitación de velocidad, disyuntor y resiliencia
  • Caché semántica, idempotencia y seguimiento del progreso
  • Operaciones de base de datos y esquema (21 módulos de base de datos)
  • Flujos de OAuth y autenticación
  • Validación de endpoints de API (Zod v4)
  • Herramientas del servidor MCP y aplicación de ámbitos
  • Sistemas de memoria y habilidades

Estilo del código

  • ESLint — Ejecuta npm run lint antes de confirmar cambios
  • Prettier — Formateado automáticamente mediante lint-staged al confirmar cambios (2 espacios, punto y coma, comillas dobles, ancho de 100 caracteres, comas finales es5)
  • TypeScript — Todo el código de src/ usa .ts/.tsx; open-sse/ usa .ts/.js; documenta con TSDoc (@param, @returns, @throws)
  • Sin eval() — ESLint aplica no-eval, no-implied-eval, no-new-func
  • Validación con Zod — Usa esquemas de Zod v4 para validar todas las entradas de la API
  • Nomenclatura: archivos = camelCase/kebab-case, componentes = PascalCase, constantes = UPPER_SNAKE

Gestión de errores / bloques catch vacíos

Nunca dejes un catch sin explicación. Clasifícalo en una de estas dos categorías (esto hace operativa la regla estricta «nunca ignorar silenciosamente errores en flujos SSE»):

  • Intencional (nuestra propia limpieza/telemetría de mejor esfuerzo) — un fallo aquí es esperado e inofensivo; añade un comentario de una línea que explique el motivo, sin registros (registrar cada solicitud es el ruido que esta convención evita).

    } catch {} // es normal cerrar un controlador ya cerrado después de que el cliente se desconecte
    
  • Debe registrarse (código externo/proporcionado por quien realiza la llamada, o si ignorarlo cambia el flujo de control) — conserva el catch (nunca permitas que interrumpa el flujo), pero emite un console.debug/warn contextual para que el fallo pueda detectarse.

    } catch (e) {
      console.debug("[STREAM] error en el callback onFailure:", e);
    }
    

Consulta open-sse/utils/stream.ts y open-sse/utils/streamHandler.ts para ver ejemplos aplicados.


Project Structure

src/                        # TypeScript (.ts / .tsx)
├── app/                    # Next.js 16 App Router
│   ├── (dashboard)/        # Dashboard pages (23 sections)
│   ├── api/                # API routes (51 directories)
│   └── login/              # Auth pages (.tsx)
├── domain/                 # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/                    # Core business logic (.ts)
│   ├── a2a/                # Agent-to-Agent v0.3 protocol server
│   ├── acp/                # Agent Communication Protocol registry
│   ├── compliance/         # Compliance policy engine
│   ├── db/                 # SQLite database layer (110 top-level modules + 130 migrations)
│   ├── memory/             # Persistent conversational memory
│   ├── oauth/              # OAuth providers, services, and utilities
│   ├── skills/             # Extensible skill framework
│   ├── usage/              # Usage tracking and cost calculation
│   └── localDb.ts          # Re-export layer only — never add logic here
├── middleware/              # Request middleware (promptInjectionGuard)
├── mitm/                   # MITM proxy (cert, DNS, target routing)
├── shared/
│   ├── components/         # React components (.tsx)
│   ├── constants/          # Provider definitions (329), MCP scopes, routing strategies
│   ├── utils/              # Circuit breaker, sanitizer, auth helpers
│   └── validation/         # Zod v4 schemas
└── sse/                    # SSE proxy pipeline

open-sse/                   # @omniroute/open-sse workspace
├── executors/              # 89 executor implementation modules
├── handlers/               # 11 request handlers (chat, responses, embeddings, images, etc.)
├── mcp-server/             # MCP server (107 tools, 3 transports, 32 scopes)
├── services/               # 178 top-level services (combo, autoCombo, rateLimitManager, etc.)
├── translator/             # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/            # Responses API transformer
└── utils/                  # 22 utility modules (stream, TLS, proxy, logging)

electron/                   # Electron desktop app (cross-platform)

tests/
├── unit/                   # Node.js test runner (122 test files)
├── integration/            # Integration tests
├── e2e/                    # Playwright tests
├── security/               # Security tests
├── translator/             # Translator-specific tests
└── load/                   # Load tests

docs/                       # Documentation
├── ARCHITECTURE.md         # System architecture
├── API_REFERENCE.md        # All endpoints
├── USER_GUIDE.md           # Provider setup, CLI integration
├── TROUBLESHOOTING.md      # Common issues
├── MCP-SERVER.md           # MCP server (107 tools)
├── A2A-SERVER.md           # A2A agent protocol
├── AUTO-COMBO.md           # Auto-combo engine
├── CLI-TOOLS.md            # CLI tools integration
├── COVERAGE_PLAN.md        # Test coverage improvement plan
├── openapi.yaml            # OpenAPI specification
└── adr/                    # Architecture Decision Records

Añadir un nuevo proveedor

Paso 1: Registrar las constantes del proveedor

Añádelas a src/shared/constants/providers.ts; se validan con Zod al cargar el módulo.

Paso 2: Añadir un ejecutor (si se necesita lógica personalizada)

Crea un ejecutor en open-sse/executors/your-provider.ts que extienda el ejecutor base.

Paso 3: Añadir un traductor (si el formato no es OpenAI)

Crea traductores de solicitudes/respuestas en open-sse/translator/.

Paso 4: Añadir la configuración de OAuth (si se basa en OAuth)

Añade las credenciales de OAuth en src/lib/oauth/constants/oauth.ts y el servicio en src/lib/oauth/services/.

Si el proveedor de origen distribuye un client_id/secreto de OAuth público o una clave de API web de Firebase dentro de su CLI pública o paquete para navegador, no lo insertes como un literal de cadena. Usa resolvePublicCred() de open-sse/utils/publicCreds.ts y añade una entrada de bytes enmascarados a EMBEDDED_DEFAULTS. El flujo de trabajo completo y obligatorio está documentado en docs/security/PUBLIC_CREDS.md.

Dentro de los controladores/ejecutores, los mensajes de error que lleguen al cliente deben pasar por buildErrorBody() / sanitizeErrorMessage() de open-sse/utils/error.ts; nunca incluyas err.stack ni err.message sin procesar en el cuerpo de una respuesta. Consulta docs/security/ERROR_SANITIZATION.md.

Paso 5: Registrar los modelos

Añade las definiciones de los modelos en open-sse/config/providerRegistry.ts.

Paso 6: Añadir pruebas

Escribe pruebas unitarias en tests/unit/ que cubran, como mínimo:

  • Registro del proveedor
  • Traducción de solicitudes/respuestas
  • Gestión de errores

Lista de verificación de la solicitud de incorporación de cambios

  • Las pruebas pasan (npm test)
  • El linting pasa (npm run lint)
  • La compilación se completa correctamente (npm run build)
  • Se añadieron tipos de TypeScript para las nuevas funciones e interfaces públicas
  • No hay secretos ni valores de respaldo codificados de forma fija
  • Las credenciales públicas de upstream están integradas mediante resolvePublicCred() (consulta docs/security/PUBLIC_CREDS.md), nunca como literales
  • Las respuestas de error pasan por buildErrorBody() / sanitizeErrorMessage(); no hay trazas de pila sin procesar en los cuerpos de las respuestas (consulta docs/security/ERROR_SANITIZATION.md)
  • Los comandos de shell (exec / spawn) pasan los valores en tiempo de ejecución mediante env, no mediante interpolación de cadenas
  • Todas las entradas se validan con esquemas de Zod
  • Se añadió un fragmento del registro de cambios en changelog.d/{features|fixes|maintenance}/<PR>-<slug>.md para los cambios visibles para el usuario (consulta changelog.d/README.md); no edites CHANGELOG.md directamente; los fragmentos se agregan en el momento de la publicación y nunca generan conflictos entre solicitudes de incorporación de cambios
  • Se actualizó la documentación (si corresponde)
  • No se abrieron nuevas alertas de CodeQL / Secret-Scanning, o cada una se descartó con una justificación técnica que hace referencia al documento pertinente de docs/security/
  • Las rutas que generan procesos secundarios (/api/mcp/, /api/cli-tools/runtime/) están clasificadas como isLocalOnlyPath() en src/server/authz/routeGuard.ts; consulta la Regla estricta n.º 15
  • No hay pies Co-Authored-By en los mensajes de commit; los commits deben aparecer únicamente bajo la identidad de Git del propietario del repositorio (Regla estricta n.º 16)

Releasing

Releases are managed via the /generate-release workflow. When a new GitHub Release is created, the package is automatically published to npm via GitHub Actions.


Obtener ayuda