services/api/src/scripts/lib/seedTargetGuard.js
Overview
Este módulo protege el arranque de seed.js con una validación estricta del destino MongoDB. Su propósito es permitir solo bases locales de desarrollo y rechazar cualquier URI remota, ambigua o con señales de staging o producción antes de conectar. La lógica es pura y no abre conexiones ni expone credenciales.
En el flujo del seed, esta guardia evita escribir usuarios de prueba, planes y anuncios sobre Atlas, staging o destinos mal interpretados. La documentación del seed confirma que evaluateSeedTarget se ejecuta antes de conectar y que el script falla cerrado cuando el destino no es local.
[!IMPORTANT] El criterio principal no es
NODE_ENV. El módulo decide primero por el host y la base de datos de la URI, y usaNODE_ENVyAPP_ENVcomo capa adicional.
How it works
flowchart TD
U[MongoDB URI] --> D[describeMongoTarget]
D --> T[target summary]
T --> E[evaluateSeedTarget]
E --> L[LOCAL_HOSTS]
E --> B[FORBIDDEN_DATABASE_RE]
E --> N[FORBIDDEN_ENVIRONMENTS]
L --> R[reasons]
B --> R
N --> R
R --> A[allowed result]
Primero, describeMongoTarget extrae esquema, hosts y base desde la URI. Luego, evaluateSeedTarget revisa si el destino usa mongodb+srv, si contiene hosts no locales, si la base falta, si la base parece de staging o producción, y si NODE_ENV o APP_ENV indican un entorno bloqueado. El resultado final resume la decisión con allowed, reasons y un target sanitizado.
Key components
Funciones exportadas
{
"title": "describeMongoTarget",
"content": "Analiza una URI MongoDB y devuelve un resumen sin credenciales: esquema, hosts sin puerto y nombre de base. Devuelve null si la URI no se puede interpretar.",
"type": "function",
"filePath": "services/api/src/scripts/lib/seedTargetGuard.js",
"badges": [
"public"
]
}
{
"title": "evaluateSeedTarget",
"content": "Eval\u00faa si un destino MongoDB es aceptable para el seed local. Devuelve una decisi\u00f3n booleana, las razones de rechazo y un resumen sanitizado del destino.",
"type": "function",
"filePath": "services/api/src/scripts/lib/seedTargetGuard.js",
"badges": [
"public"
]
}
Elementos internos
LOCAL_HOSTS—Setconlocalhost,127.0.0.1y::1. Solo esos hosts se aceptan como locales.FORBIDDEN_DATABASE_RE— expresión regular que detecta nombres de base con señales destaging,stage,stg,prod,productionolive.FORBIDDEN_ENVIRONMENTS—Setconproductionystaging. Si cualquiera aparece enNODE_ENVoAPP_ENV, la evaluación falla.stripPort(host)— helper que elimina el puerto del host y maneja hosts IPv6 entre corchetes.
Data & fields
describeMongoTarget(uri) devuelve un resumen sanitizado
[
{
"name": "scheme",
"type": "string",
"required": true,
"description": "Esquema detectado. El módulo acepta mongodb y mongodb+srv."
},
{
"name": "hosts",
"type": "string[]",
"required": true,
"description": "Lista de hosts en minúsculas y sin puerto."
},
{
"name": "database",
"type": "string",
"required": true,
"description": "Nombre de la base extraído de la ruta de la URI y decodificado."
}
]
El resumen nunca incluye usuario, contraseña ni parámetros de query. Los tests verifican que una URI con credenciales y authSource sigue devolviendo solo scheme, hosts y database.
evaluateSeedTarget({ uri, nodeEnv, appEnv }) usa estas entradas
[
{
"name": "uri",
"type": "string",
"required": true,
"description": "URI MongoDB que se quiere evaluar."
},
{
"name": "nodeEnv",
"type": "string",
"description": "Valor de NODE_ENV usado como capa adicional de bloqueo."
},
{
"name": "appEnv",
"type": "string",
"description": "Valor de APP_ENV usado como capa adicional de bloqueo."
}
]
evaluateSeedTarget(...) devuelve este objeto
[
{
"name": "allowed",
"type": "boolean",
"required": true,
"description": "Indica si la URI pasa todas las reglas."
},
{
"name": "reasons",
"type": "string[]",
"required": true,
"description": "Lista de códigos de rechazo. Cada razón identifica una causa concreta."
},
{
"name": "target",
"type": "object | null",
"required": true,
"description": "Resumen sanitizado del destino, o null si la URI no se puede interpretar.",
"children": [
{
"name": "hosts",
"type": "string[]",
"required": true,
"description": "Hosts locales o remotos detectados en la URI, ya normalizados."
},
{
"name": "database",
"type": "string",
"required": true,
"description": "Nombre de la base detectado en la ruta."
}
]
}
]
Códigos de razón que emite el módulo
URI_UNPARSEABLE— la URI no se pudo interpretar como MongoDB.SRV_NOT_ALLOWED—mongodb+srvno se permite.REMOTE_HOST— existe al menos un host fuera deLOCAL_HOSTS.DATABASE_MISSING— la URI no declara una base explícita.DATABASE_FORBIDDEN— el nombre de base parece de staging o producción.ENVIRONMENT_FORBIDDEN—NODE_ENVoAPP_ENVapuntan a staging o producción.
Behaviors
describeMongoTarget(uri)— analiza una URI MongoDB, normaliza hosts, decodifica la base y devuelvenullsi no hay coincidencia válida.evaluateSeedTarget({ uri, nodeEnv, appEnv })— ejecuta la política de bloqueo y devuelve el veredicto final con razones y resumen del destino.stripPort(host)— elimina el puerto de un host normal y maneja direcciones IPv6 con corchetes.LOCAL_HOSTS— define los únicos hosts aceptados como locales.FORBIDDEN_DATABASE_RE— detecta bases con nombres asociados a entornos no locales.FORBIDDEN_ENVIRONMENTS— bloquea entornos declarados comoproductionostaging.
Gotchas & edge cases
[!WARNING] Si la URI usa
mongodb+srv, el módulo la rechaza aunque apunte a un nombre de base local. La razón es que ese esquema siempre apunta a un cluster remoto. fileciteturn0file2turn0file11
[!WARNING] Un host mixto también falla. Si la URI combina un host local con uno remoto,
REMOTE_HOSTentra enreasons.
[!IMPORTANT] Una URI sin base explícita no pasa.
mongodb://localhost:27017se considera inválida porDATABASE_MISSING.
[!NOTE] El módulo falla cerrado ante entradas vacías, texto que no parece URI y esquemas distintos de MongoDB. Los tests cubren esos casos ambiguos o ilegibles.
[!NOTE]
describeMongoTargetno conserva credenciales ni query params. La salida está pensada para mensajes de error seguros y para evaluación interna. fileciteturn0file2turn0file7
[!CAUTION] Un
NODE_ENV=developmentno basta para permitir el destino. Si la URI apunta a remoto,evaluateSeedTargetsigue rechazando.
Related
services/api/src/scripts/seed.js usa evaluateSeedTarget como puerta de entrada antes de conectar a MongoDB. La documentación del seed indica que el proceso sale con código 1 si el destino no pasa esta validación.
services/api/src/scripts/lib/localMongoTarget.js reutiliza describeMongoTarget y evaluateSeedTarget para una política más estricta en herramientas administrativas. Allí se añaden reglas sobre opciones de URI y validación posterior de hello.
services/api/test/seed-target-guard.test.js confirma el comportamiento esperado. Cubre destinos locales válidos, rechazo de mongodb+srv, bloqueo por nombres de base, bloqueo por entorno y protección contra filtrado de credenciales. fileciteturn0file4turn0file7turn0file11
[!TIP] Este módulo funciona como una barrera de seguridad previa a cualquier escritura del seed. Su valor está en decidir antes de conectar, no después.