Pokémon DevOps Platform

September 24, 2026 · View on GitHub

Plataforma full-stack y referencia de arquitectura DevSecOps que implementa una Pokédex reactiva para la consulta y gestión del catálogo oficial de Pokémon. Diseñada bajo principios de separación de responsabilidades, seguridad por defecto (fail-closed) y despliegue continuo mediante contenedores y orquestación con Kubernetes y GitOps.

CI Pipeline Node.js TypeScript Docker Kubernetes Helm Security: Gitleaks License: MIT


📑 Tabla de Contenidos


Demo y Acceso Rápido

Al iniciar la plataforma en el entorno local, los servicios quedan disponibles en:

  • Interfaz Web (Catálogo): http://localhost:8080
  • Panel de Administración (Backoffice): http://localhost:8080/backoffice.html
  • API REST Backend: http://localhost:3000
  • Healthcheck de Preparación: http://localhost:3000/readyz
  • Métricas Prometheus: http://localhost:3000/metrics
  • Portal de Documentación: docs/README.md

Características Principales


Arquitectura del Sistema

La solución desacopla la capa de presentación, la lógica de negocio y los servicios de datos:

flowchart TD
    User(["👤 Usuario / Cliente"]) -->|HTTP 8080| Proxy["🌐 Nginx Reverse Proxy\napps/frontend"]
    Proxy -->|Assets Estáticos| Web["📦 SPA Vite + TS"]
    Proxy -->|Proxy /api/*, /pokemons| API["⚙️ API Express + TS\napps/backend :3000"]
    
    API -->|SQL :5432| DB[("🗄️ PostgreSQL 16\npokedex_entries")]
    API -->|RESP :6379| Cache[("⚡ Redis 7\nCaché & Sesiones")]
    API -->|HTTPS| AI["🤖 Google Gemini 2.5 Flash\nServicio de IA"]

    subgraph GitOps_Flow ["☸️ Despliegue GitOps"]
        GH["🐙 GitHub Actions"] -->|Build, SBOM & Sign| OCI["📦 GitHub Packages (GHCR)"]
        Argo["🚀 ArgoCD"] -->|Sync Declarativo| K8s["☸️ Clúster Kubernetes"]
        OCI -.->|Pull por Digest Inmutable| K8s
    end

Para una descripción exhaustiva de la arquitectura, flujos de datos y contratos de red, consulta docs/architecture/ANALISIS_LENGUAJES_Y_MEJORES_PRACTICAS.md y docs/architecture/SECURITY_AND_NETWORK_ISOLATION.md.


Requisitos

Para ejecutar y colaborar en el proyecto se requiere:

  • Node.js 22 LTS y npm 10+
  • Docker 24+ y Docker Compose v2
  • Task (recomendado como ejecutor de tareas unificado)
  • Helm 3.17+ y Kind (opcional, para validación sobre Kubernetes local)

Inicio Rápido

Sigue estos pasos para levantar la plataforma en tu entorno de desarrollo en menos de dos minutos:

1. Clonar el repositorio

git clone https://github.com/rocapellino/pokedex.git
cd pokedex

2. Configurar variables de entorno

Copia la plantilla de configuración e inicializa el archivo .env:

cp .env.example .env

Note

En desarrollo local los valores por defecto de .env.example permiten arrancar sin configuración adicional. Si deseas habilitar funciones de IA, añade tu clave GEMINI_API_KEY.

3. Instalar dependencias

Instala las dependencias del monorepo de forma limpia y reproducible con task o npm:

task install
# O equivalente: npm ci

4. Iniciar la aplicación

Puedes utilizar task o docker compose directamente:

# Con Task (recomendado):
task dev:compose

# O directamente con Docker Compose:
docker compose up -d

Este comando inicia los contenedores de PostgreSQL 16, Redis 7, el Backend Express y el Frontend Nginx con inicialización automática de datos.

5. Verificar el servicio

Comprueba la salud del proceso y la conectividad activa con las bases de datos:

# Con Task (verifica liveness, readiness y frontend):
task dev:verify

# O manualmente con curl:
# Liveness (el proceso Node.js responde):
curl -s http://localhost:3000/healthz

# Readiness (PostgreSQL y Redis conectados y listos para tráfico):
curl -s http://localhost:3000/readyz
# Salida esperada: {"status":"ready","database":"connected","redis":"connected"}

Abre tu navegador en http://localhost:8080 para explorar el catálogo interactivo.

6. Detener los servicios

task dev:compose:down
# O bien: docker compose down

Comandos Disponibles

El proyecto utiliza un Taskfile.yml como interfaz de desarrollo estandarizada, complementado con scripts de package.json:

ComandoHerramientaPropósito
task install / npm cinpmInstala dependencias del monorepo de forma limpia y reproducible.
npm run lintTypeScriptValida tipos y reglas de sintaxis en apps/backend y apps/frontend.
npm run typecheckTypeScriptEjecuta la verificación estricta de tipos (tsc --noEmit) en la raíz.
npm run buildesbuild / ViteCompila el backend a CommonJS y genera el bundle optimizado del frontend.
npm testNode Test RunnerEjecuta la suite automatizada de pruebas unitarias, de integración, seguridad y DR.
npm run test:fuzzScript dinámicoEjecuta pruebas de fuzzing con cargas malformadas sobre los endpoints.
task validateMonorepo ScriptEjecuta todas las validaciones obligatorias del proyecto en un solo paso.
task dev:composeDocker ComposeLevanta el stack multicontenedor local (API, Web, DB, Redis).
task dev:compose:downDocker ComposeDetiene y remueve los contenedores del entorno local de Compose.
task dev:verifycURL / ScriptValida la disponibilidad HTTP y salud de los servicios locales (healthz, readyz, web).
task dev:k8s:upKind + HelmCrea un clúster Kind local y despliega el Helm chart con Ingress.
task dev:k8s:statuskubectlMuestra el estado de Pods, Services e Ingress en Kubernetes local.
task dev:k8s:downKindElimina el clúster Kind local y libera sus recursos.
task dr:verifyBash / DockerEjecuta el simulacro automatizado de Disaster Recovery en PostgreSQL efímero.
task helm:lintHelm en DockerValida sintácticamente las plantillas del chart de Helm de forma reproducible.

Configuración

Las variables de entorno se definen en el archivo .env tomando como base .env.example:

VariableObligatoriaEjemploDescripciónEntorno
NODE_ENVSídevelopmentModo de ejecución de la aplicación (development, production, test).Todos
PORTNo3000Puerto HTTP en el que escucha el servidor backend (por defecto 3000).Backend
WEB_PORTNo8080Puerto HTTP expuesto por el proxy Nginx en Compose.Frontend
DATABASE_URLSí en prodpostgresql://user:pass@localhost:5432/pokedexCadena de conexión principal hacia PostgreSQL 16.Backend
REDIS_URLSí en prodredis://localhost:6379Conexión hacia Redis 7 para rate limiting y caché.Backend
ADMIN_API_KEYSí en prodopenssl rand -hex 32Credencial maestra para endpoints de gestión y emisión de sesiones.Backend
ADMIN_SESSION_SECRETSí en prodopenssl rand -hex 32Secreto HMAC utilizado para firmar y verificar tokens de sesión Bearer.Backend
CORS_ORIGINSSí en prodhttps://pokedex.example.comLista de orígenes autorizados separados por coma.Backend
GEMINI_API_KEYOpcionalAIzaSy...Clave de Google AI Studio para activar generación con Gemini 2.5 Flash.Backend
DR_BACKUP_KEYOpcionalclave-secreta-drClave de descifrado AES-256 para validación de backups de DR.DR / Scripts

Warning

Nunca incorpores credenciales reales, tokens o claves privadas al repositorio. En producción, las contraseñas deben gestionarse mediante Kubernetes Secrets o proveedores externos como External Secrets Operator.


API REST

La API expone endpoints para la consulta pública y la administración autenticada del catálogo.

Endpoints Principales

MétodoEndpointAutenticaciónDescripción
GET/healthzPúblicaComprueba que el proceso de la aplicación esté activo (liveness).
GET/readyzPúblicaVerifica conectividad con PostgreSQL y Redis (readiness).
GET/metricsPúblicaExpone métricas en formato estándar de Prometheus.
GET/versionPúblicaRetorna metadatos de versión y commit SHA inyectados durante el build.
GET/pokemonsPúblicaLista paginada del catálogo (soporta filtros type y search).
GET/pokemons/:idPúblicaDetalle de un Pokémon por su ID nacional (1 - 1025).
POST/api/v1/auth/sessionX-API-KeyIntercambia la API Key administrativa por un token de sesión HMAC Bearer.
POST/api/v1/auth/logoutBearer TokenRevoca la sesión en Redis de forma inmediata.
POST/pokemonsBearer TokenRegistra un nuevo Pokémon en la base de datos.
PUT/pokemons/:idBearer TokenActualiza los datos de un Pokémon e invalida la caché.
DELETE/pokemons/:idBearer TokenElimina un registro del catálogo e invalida la caché.
POST/api/v1/ai/diagramBearer TokenGenera un diagrama de arquitectura en sintaxis Mermaid con IA.

Ejemplos de Solicitud

# Consultar Pokémon por ID con cabecera ETag
curl -s http://localhost:3000/pokemons/25

# Paginación del catálogo con límite y búsqueda
curl -s "http://localhost:3000/pokemons?limit=5&offset=0&type=Electric"

# Verificación de salud y dependencias
curl -s http://localhost:3000/readyz

Testing y Calidad

El proyecto mantiene una suite automatizada de pruebas y quality gates:

# Ejecutar suite automatizada de pruebas
npm test

# Ejecutar verificación estricta de tipos
npm run typecheck

# Ejecutar linting en todos los workspaces
npm run lint

# Ejecutar validación completa obligatoria (lint, typecheck, build, test, fuzz)
npm run validate

# Ejecutar pruebas de resistencia con payloads malformados
npm run test:fuzz

En integración continua (GitHub Actions), cada Pull Request debe superar satisfactoriamente:

  • Pruebas Unitarias y de Integración: Pruebas con el Node Test Runner nativo sobre servicios, API y validaciones.
  • Seguridad SAST: Semgrep y GitHub CodeQL analizando reglas OWASP Top 10.
  • Seguridad SCA & Secretos: Gitleaks contra filtración de credenciales y Dependency Review para bloqueo de dependencias vulnerables.
  • Seguridad IaC: Checkov escaneando Dockerfiles, Helm charts y manifiestos de OpenTofu.
  • Integración Canónica en Kind: Despliegue real del Helm chart en clúster efímero validando Pods, Ingress y probes.

Estrategia de Despliegue

La plataforma diferencia claramente los propósitos de cada entorno de ejecución:

Entorno / CapaTecnología PrincipalRol y Propósito
Desarrollo LocalDocker Compose (docker-compose.yml)Iteración rápida para desarrollo y pruebas interactivas.
Integración Local / CIKubernetes + Kind (task dev:k8s:up)Validación idéntica a producción (Ingress, Probes, NetPols).
Producción On-PremiseKubernetes sobre Proxmox VEDespliegue continuo gobernado por ArgoCD y Helm.
Producción CloudKubernetes sobre AWS EKSInfraestructura escalable gestionada mediante OpenTofu.
Aprovisionamiento IaCOpenTofu (infra/opentofu)Declaración reproducible de infraestructura (Terraform retirado).
Hardening de ServidoresAnsible (infra/ansible)Configuración base, UFW, módulos de kernel y Docker en nodos.
EmpaquetadoHelm 3 (infra/helm/pokedex)Plantillas parametrizadas con HPA, PDB y NetworkPolicies.
Entrega Continua (GitOps)ArgoCD (gitops/)Sincronización declarativa basada en digests OCI inmutables.

Important

Docker Compose está destinado exclusivamente al desarrollo local interactivo. En producción, ArgoCD es la fuente de verdad y el mecanismo oficial de sincronización continua. Helm 3 se utiliza para empaquetar y renderizar los manifiestos inmutables. El uso directo de kubectl apply está reservado exclusivamente para el bootstrap inicial o contingencias documentadas.

Matriz de Estado y Nivel de Soporte de Componentes

Componente / SubsistemaNivel de SoporteRol y Alcance Técnico
Kubernetes (EKS / Bare-Metal)OficialRuntime estándar y mandatorio de producción, staging y pruebas canónicas de integración en Kind.
Helm 3 (OCI Artifacts)OficialEmpaquetado canónico, versionado semántico y plantillas parametrizadas con firmas Cosign y SBOM.
ArgoCD (GitOps)OficialSincronización continua declarativa y reconciliación de estado hacia clústeres gestionados.
OpenTofu 1.8+OficialAprovisionamiento declarativo de infraestructura cloud (AWS EKS), entornos de laboratorio y Proxmox con gestión y cifrado de estados formalizado en docs/decisions/ADR-012-iac-state-management-and-encryption.md.
Ansible (host_baseline)OficialHardening del SO base, cortafuegos UFW, módulos de kernel y preparación de nodos físicos/VMs.
Docker ComposeSoporte / DevEntorno de desarrollo local rápido y contingencia aislada para ejecución sin clúster Kubernetes.
Backup & DR (AES-256 + SHA-256)OficialCronJob nativo en K8s con cifrado PBKDF2/AES-256-CBC, pruebas automatizadas en contenedor efímero (RPO < 24h, RTO < 2h).
Observabilidad & PrometheusOficialMétricas RED, histogramas de latencia en backend, recurso ServiceMonitor y Runbook Operacional.
External Secrets Operator (ESO)ReferenciaArquitectura declarativa para sincronización y rotación dinámica de secretos desde Vault / Cloud KMS.

Observabilidad

El sistema está instrumentado para integrarse nativamente con stacks de observabilidad estándar (Prometheus Operator, Grafana, Loki y Alertmanager):

  • Métricas RED & Negocio: Expuestas en /metrics mediante cliente nativo Prometheus (latencias HTTP de alta resolución con percentiles P95/P99, códigos de estado, estado de almacenamiento PostgreSQL y Redis en vivo).
  • Integración Prometheus Operator: Manifiesto declarativo ServiceMonitor empaquetado en Helm y habilitado en values.prod.yaml.
  • Healthchecks: /healthz para comprobación de vida del proceso y /readyz para estado de dependencias activas (PostgreSQL y Redis) bajo semántica fail-closed.
  • Logs Estructurados: Salida estándar JSON de alto rendimiento con Pino, inyección y propagación de X-Request-Id y correlación distribuida vía AsyncLocalStorage.
  • Runbook Operativo de Alertas: Procedimientos estándar de diagnóstico y mitigación para las 6 alertas de Prometheus en docs/operations/observability-alerts.md.
  • Decisión de Diseño: Registro formal de arquitectura en docs/decisions/ADR-007-observability-and-metrics.md.

Note

La observabilidad central está migrada a Grafana Cloud mediante Grafana Alloy DaemonSet y Beyla eBPF (task monitoring:grafana-cloud:install). Los tableros canónicos se encuentran versionados en infra/monitoring/dashboards/ y las alertas en infra/monitoring/alerts.yml. El stack local docker_monitoreo se mantiene como opción secundaria para emulación local con Docker Compose.


Backup y Disaster Recovery

La estrategia de respaldo y recuperación ante desastres contempla:

  • Respaldos periódicos de PostgreSQL generados con compresión gzip y cifrado simétrico AES-256-CBC con PBKDF2 y checksum SHA-256.
  • Script de validación automatizado (scripts/dr_verify_restore.sh) que efectúa restauraciones de prueba en un contenedor PostgreSQL efímero aislado fijado por digest (postgres:16-alpine@sha256:...), comprobando integridad de esquemas, Primary Keys, secuencias y recuento de registros bajo política estricta fail-closed.

Para consultar los procedimientos paso a paso y la arquitectura de respaldo, revisa el Plan de Disaster Recovery.


Seguridad

La seguridad está integrada en todas las capas del ciclo de vida:

  • Supply Chain Security: Las imágenes OCI publicadas en GitHub Packages son firmadas criptográficamente con Cosign (modo keyless con Sigstore OIDC) y cuentan con atestaciones de SBOM en formato CycloneDX y SLSA Provenance.
  • Control de Admisión: En Kubernetes, políticas de Kyverno verifican la firma de las imágenes antes de autorizar la creación de Pods.
  • Network Isolation: Políticas de red Zero-Trust (Default-Deny Egress) en PostgreSQL y Redis, microsegmentación en 4 capas y filtrado anti-SSRF formalizado en docs/decisions/ADR-013-zero-trust-network-architecture.md.
  • Comparaciones Timing-Safe: Autenticación administrativa protegida contra ataques de canal lateral basados en tiempo y arquitectura de sesiones formalizada en docs/decisions/ADR-010-authentication-and-session-management.md.
  • Decisión de Diseño: Registro formal de arquitectura de seguridad en la cadena de suministro en docs/decisions/ADR-008-supply-chain-security.md.

Para conocer el procedimiento de divulgación responsable o reportar una vulnerabilidad, consulta SECURITY.md.


Estructura del Repositorio

.
├── apps/
│   ├── backend/                     # API REST Express + TypeScript + Drizzle ORM
│   │   ├── Dockerfile               # Contenedor Alpine no-root (Node.js 22 LTS)
│   │   ├── server.ts                # Servidor Express, middlewares y rutas
│   │   └── src/                     # Lógica de negocio, base de datos y esquemas
│   └── frontend/                    # SPA Vite + TypeScript + DOMPurify
│       ├── Dockerfile               # Servidor Nginx Alpine con build multi-stage
│       ├── nginx.conf               # Configuración optimizada con cabeceras de seguridad
│       └── src/                     # Componentes y controladores de interfaz
├── infra/
│   ├── ansible/                     # Hardening de SO y preparación de nodos (host_baseline.yml)
│   ├── helm/pokedex/                # Helm Chart 3 parametrizado (HPA, NetPols, Secrets)
│   ├── k8s/                         # Configuración de clúster Kind local y políticas Kyverno
│   ├── opentofu/                    # Infraestructura como Código (Proxmox VE + AWS EKS)
│   └── proxmox/                     # Plantillas Cloud-Init y contenedores LXC
├── gitops/
│   ├── apps/                        # Definiciones de Application y App-of-Apps para ArgoCD
│   ├── environments/                # Values específicos por clúster (on-premise y cloud)
│   └── health-checks/               # Evaluaciones de salud Lua para CRDs en ArgoCD
├── scripts/                         # Utilidades de auditoría, verificación DR y testing
├── tests/                           # Suite de pruebas automatizadas
├── .github/workflows/               # Pipelines de CI/CD, SAST, DAST, IaC y Supply Chain
├── docker-compose.yml               # Orquestación de desarrollo local interactivo
├── package.json                     # Monorepo workspaces y dependencias compartidas
└── Taskfile.yml                     # Automatizador de comandos del proyecto (Task)

Documentación Adicional

La documentación técnica detallada se encuentra organizada en el directorio docs/:


Resolución de Problemas (Troubleshooting)

El puerto 8080 o 3000 ya está en uso

Si Docker Compose o un proceso local ya ocupa los puertos:

# Detener contenedores existentes
docker compose down

# En Linux / macOS: identificar proceso ocupando el puerto
lsof -i :8080
lsof -i :3000

# En Windows (PowerShell):
Get-NetTCPConnection -LocalPort 8080,3000 | Select-Object LocalPort,OwningProcess

/readyz devuelve error o dependencias no conectadas

Verifica el estado de los contenedores de datos y sus logs:

docker compose ps
docker compose logs postgres
docker compose logs redis

Asegúrate de que las credenciales en .env coincidan con los parámetros de conexión.

El frontend Web carga pero la API no responde

Comprueba la comunicación de red entre el contenedor de Nginx y el backend:

docker compose logs backend
curl -s http://localhost:3000/healthz

En entornos Kubernetes, verifica que el servicio pokemon-api-svc tenga endpoints activos:

kubectl get endpoints pokemon-api-svc -n pokemon-app

Kind no puede cargar o encontrar las imágenes locales

Si despliegas en Kubernetes local y los pods quedan en ImagePullBackOff o ErrImageNeverPull:

# Verificar que el clúster exista
kind get clusters

# Recompilar y cargar las imágenes en el plano de control de Kind
docker build -t pokedex-api:local -f apps/backend/Dockerfile .
docker build -t pokedex-web:local -f apps/frontend/Dockerfile .
kind load docker-image pokedex-api:local --name pokedex-local
kind load docker-image pokedex-web:local --name pokedex-local

Licencia

Este proyecto está licenciado bajo los términos de la Licencia MIT. Consulta el archivo LICENSE para más detalles.