clinica-dental/orchestration/environment/ENVIRONMENT-INVENTORY.yml
rckrdmrd 7ffcdf597c feat: Initial commit - clinica-dental
ERP especializado para clínicas dentales.

Estructura inicial:
- database/ (PostgreSQL DDL)
- docs/ (Documentación)
- orchestration/ (Sistema NEXUS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:41:50 -06:00

805 lines
23 KiB
YAML

# =============================================================================
# ENVIRONMENT-INVENTORY.yml - CLINICA-DENTAL
# =============================================================================
# Inventario Completo de Entorno de Desarrollo y Produccion
# Generado por: @PERFIL_DEVENV
# Basado en: orchestration/templates/TEMPLATE-ENVIRONMENT-INVENTORY.yml
# =============================================================================
version: "1.1.0"
fecha_creacion: "2026-01-04"
fecha_actualizacion: "2026-01-04"
responsable: "@PERFIL_DEVENV"
# -----------------------------------------------------------------------------
# IDENTIFICACION DEL PROYECTO
# -----------------------------------------------------------------------------
proyecto:
nombre: "Clinica Dental"
alias: "clinica-dental"
codigo: "CD"
nivel: "NIVEL_2B.3"
tipo: "vertical-especializada"
estado: "desarrollo"
descripcion: "Sistema de gestion para clinicas dentales y odontologicas"
parent: "erp-clinicas"
herencia:
- erp-core
- erp-clinicas
normativas:
- "NOM-024-SSA3-2012 (Expediente clinico electronico)"
- "NOM-013-SSA2-2015 (Prevencion y control enfermedades bucales)"
# -----------------------------------------------------------------------------
# HERRAMIENTAS Y RUNTIME
# -----------------------------------------------------------------------------
herramientas:
runtime:
node:
version: "20.x"
version_minima: "18.x"
requerido: true
notas: "LTS recomendado para NestJS y React"
python:
version: ""
requerido: false
notas: "No requerido para este proyecto"
package_managers:
npm:
version: "10.x"
requerido: true
pnpm:
version: "8.x"
requerido: false
notas: "Alternativa opcional"
build_tools:
- nombre: "Vite"
version: "5.x"
uso: "Frontend build y dev server"
- nombre: "TypeScript"
version: "5.x"
uso: "Compilacion de codigo"
- nombre: "NestJS CLI"
version: "10.x"
uso: "Backend scaffolding y build"
linters:
- nombre: "ESLint"
version: "8.x"
config: ".eslintrc.js"
- nombre: "Prettier"
version: "3.x"
config: ".prettierrc"
testing:
- nombre: "Jest"
version: "29.x"
tipo: "unit backend"
config: "jest.config.js"
- nombre: "Vitest"
version: "1.x"
tipo: "unit frontend"
config: "vitest.config.ts"
- nombre: "Supertest"
version: "6.x"
tipo: "e2e"
config: "jest-e2e.config.js"
# -----------------------------------------------------------------------------
# SERVICIOS Y PUERTOS
# -----------------------------------------------------------------------------
servicios:
frontend:
nombre: "clinica-dental-frontend"
framework: "React"
version: "18.x"
puerto: 3130
comando_dev: "npm run dev"
comando_build: "npm run build"
comando_preview: "npm run preview"
ubicacion: "apps/frontend/"
url_local: "http://localhost:3130"
build_output: "dist/"
backend:
nombre: "clinica-dental-backend"
framework: "NestJS"
version: "10.x"
puerto: 3131
comando_dev: "npm run start:dev"
comando_build: "npm run build"
comando_prod: "npm run start:prod"
ubicacion: "apps/backend/"
url_local: "http://localhost:3131"
api_prefix: "/api/v1"
swagger_url: "http://localhost:3131/api/docs"
# -----------------------------------------------------------------------------
# BASE DE DATOS - CONFIGURACION COMPLETA
# -----------------------------------------------------------------------------
base_de_datos:
principal:
engine: "PostgreSQL"
version: "15"
host_variable: "DB_HOST"
puerto_variable: "DB_PORT"
ambientes:
development:
host: "localhost"
puerto: 5441
nombre: "clinica_dental_dev"
usuario: "dental_dev"
password_ref: "DB_PASSWORD en .env"
ssl: false
pool_size: 10
conexion: "postgresql://dental_dev:{password}@localhost:5441/clinica_dental_dev"
test:
host: "localhost"
puerto: 5441
nombre: "clinica_dental_test"
usuario: "dental_dev"
password_ref: "DB_PASSWORD en .env"
ssl: false
pool_size: 5
conexion: "postgresql://dental_dev:{password}@localhost:5441/clinica_dental_test"
staging:
host: "${DB_HOST}"
puerto: 5432
nombre: "clinica_dental_staging"
usuario: "dental_staging"
password_ref: "DB_PASSWORD en variables de CI/CD"
ssl: true
pool_size: 20
conexion: "postgresql://dental_staging:{password}@${DB_HOST}:5432/clinica_dental_staging?sslmode=require"
production:
host: "${DB_HOST}"
puerto: 5432
nombre: "clinica_dental_prod"
usuario: "dental_prod"
password_ref: "DB_PASSWORD en secrets manager"
ssl: true
pool_size: 50
conexion: "postgresql://dental_prod:{password}@${DB_HOST}:5432/clinica_dental_prod?sslmode=require"
schemas:
- nombre: "public"
descripcion: "Schema principal PostgreSQL"
- nombre: "dental"
descripcion: "Entidades odontologicas (odontograma, piezas, tratamientos, ortodoncia)"
- nombre: "clinical"
descripcion: "Heredado de erp-clinicas (consultorios, citas, historiales)"
- nombre: "financial"
descripcion: "Heredado de erp-core (pagos, facturacion, presupuestos)"
- nombre: "hr"
descripcion: "Heredado de erp-core (empleados, especialidades)"
- nombre: "inventory"
descripcion: "Heredado de erp-core (materiales, insumos dentales)"
scripts_inicializacion:
orden:
- "database/init/00-extensions.sql"
- "database/init/01-schemas.sql"
- "database/schemas/01-dental-schema-ddl.sql"
- "database/seeds/fase8/01-dental-catalogos.sql"
- "database/seeds/fase8/02-piezas-dentales-fdi.sql"
datos_iniciales:
piezas_dentales:
total: 52
nomenclatura: "FDI (Federation Dentaire Internationale)"
cuadrantes:
- id: 1
nombre: "Superior derecho"
piezas: "18-11"
tipo: "permanente"
- id: 2
nombre: "Superior izquierdo"
piezas: "21-28"
tipo: "permanente"
- id: 3
nombre: "Inferior izquierdo"
piezas: "31-38"
tipo: "permanente"
- id: 4
nombre: "Inferior derecho"
piezas: "41-48"
tipo: "permanente"
- id: 5
nombre: "Superior derecho temporal"
piezas: "55-51"
tipo: "temporal"
- id: 6
nombre: "Superior izquierdo temporal"
piezas: "61-65"
tipo: "temporal"
- id: 7
nombre: "Inferior izquierdo temporal"
piezas: "71-75"
tipo: "temporal"
- id: 8
nombre: "Inferior derecho temporal"
piezas: "81-85"
tipo: "temporal"
redis:
host_variable: "REDIS_HOST"
puerto_variable: "REDIS_PORT"
ambientes:
development:
host: "localhost"
puerto: 6388
database: 0
password: ""
conexion: "redis://localhost:6388/0"
production:
host: "${REDIS_HOST}"
puerto: 6379
database: 0
password_ref: "REDIS_PASSWORD en secrets"
conexion: "redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0"
uso:
- "Cache de sesiones"
- "Cache de odontogramas"
- "Rate limiting"
- "Queue de tareas (Bull)"
# -----------------------------------------------------------------------------
# VARIABLES DE ENTORNO - DESARROLLO
# -----------------------------------------------------------------------------
variables_entorno:
archivos:
ejemplo: ".env.example"
desarrollo: ".env"
test: ".env.test"
produccion: ".env.production"
development:
- nombre: "NODE_ENV"
valor: "development"
descripcion: "Ambiente de ejecucion"
requerido: true
sensible: false
- nombre: "APP_NAME"
valor: "clinica-dental"
descripcion: "Nombre de la aplicacion"
requerido: true
sensible: false
- nombre: "APP_VERSION"
valor: "1.0.0"
descripcion: "Version de la aplicacion"
requerido: false
sensible: false
# Puertos
- nombre: "FRONTEND_PORT"
valor: "3130"
descripcion: "Puerto del frontend React"
requerido: true
sensible: false
- nombre: "BACKEND_PORT"
valor: "3131"
descripcion: "Puerto del backend NestJS"
requerido: true
sensible: false
# Base de datos
- nombre: "DB_HOST"
valor: "localhost"
descripcion: "Host de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_PORT"
valor: "5441"
descripcion: "Puerto de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_NAME"
valor: "clinica_dental_dev"
descripcion: "Nombre de la base de datos"
requerido: true
sensible: false
- nombre: "DB_USER"
valor: "dental_dev"
descripcion: "Usuario de PostgreSQL"
requerido: true
sensible: false
- nombre: "DB_PASSWORD"
valor: ""
descripcion: "Password de PostgreSQL"
requerido: true
sensible: true
generacion: "openssl rand -base64 32"
- nombre: "DATABASE_URL"
valor: "postgresql://dental_dev:${DB_PASSWORD}@localhost:5441/clinica_dental_dev"
descripcion: "Connection string completo"
requerido: true
sensible: true
# Redis
- nombre: "REDIS_HOST"
valor: "localhost"
descripcion: "Host de Redis"
requerido: true
sensible: false
- nombre: "REDIS_PORT"
valor: "6388"
descripcion: "Puerto de Redis"
requerido: true
sensible: false
- nombre: "REDIS_URL"
valor: "redis://localhost:6388/0"
descripcion: "Connection string de Redis"
requerido: true
sensible: false
# Autenticacion
- nombre: "JWT_SECRET"
valor: ""
descripcion: "Secreto para firmar JWT (min 32 caracteres)"
requerido: true
sensible: true
generacion: "openssl rand -base64 64"
- nombre: "JWT_EXPIRES_IN"
valor: "24h"
descripcion: "Tiempo de expiracion del access token"
requerido: true
sensible: false
- nombre: "JWT_REFRESH_EXPIRES_IN"
valor: "7d"
descripcion: "Tiempo de expiracion del refresh token"
requerido: true
sensible: false
# CORS
- nombre: "FRONTEND_URL"
valor: "http://localhost:3130"
descripcion: "URL del frontend para CORS"
requerido: true
sensible: false
- nombre: "ALLOWED_ORIGINS"
valor: "http://localhost:3130,http://localhost:3131"
descripcion: "Origenes permitidos (comma separated)"
requerido: true
sensible: false
# Logging
- nombre: "LOG_LEVEL"
valor: "debug"
descripcion: "Nivel de logging (debug, info, warn, error)"
requerido: false
sensible: false
- nombre: "LOG_FORMAT"
valor: "pretty"
descripcion: "Formato de logs (pretty, json)"
requerido: false
sensible: false
# File Storage (radiografias, documentos)
- nombre: "STORAGE_TYPE"
valor: "local"
descripcion: "Tipo de storage (local, s3, minio)"
requerido: false
sensible: false
- nombre: "STORAGE_PATH"
valor: "./uploads"
descripcion: "Path para almacenamiento local"
requerido: false
sensible: false
- nombre: "MAX_FILE_SIZE"
valor: "20971520"
descripcion: "Tamano maximo de archivo en bytes (20MB para radiografias)"
requerido: false
sensible: false
- nombre: "ALLOWED_FILE_TYPES"
valor: "image/jpeg,image/png,image/dicom,application/pdf"
descripcion: "Tipos de archivo permitidos"
requerido: false
sensible: false
# Email (opcional)
- nombre: "SMTP_HOST"
valor: "localhost"
descripcion: "Host SMTP para emails"
requerido: false
sensible: false
- nombre: "SMTP_PORT"
valor: "1025"
descripcion: "Puerto SMTP (1025 para MailHog)"
requerido: false
sensible: false
# Configuracion Dental Especifica
- nombre: "DENTAL_FDI_NOTATION"
valor: "true"
descripcion: "Usar notacion FDI para piezas dentales"
requerido: false
sensible: false
- nombre: "ODONTOGRAM_VERSION"
valor: "2.0"
descripcion: "Version del formato de odontograma"
requerido: false
sensible: false
production:
notas: |
En produccion, las siguientes variables deben configurarse
via secrets manager o variables de CI/CD:
- DB_PASSWORD (secreto)
- JWT_SECRET (secreto)
- REDIS_PASSWORD (secreto)
- AWS_ACCESS_KEY_ID (si usa S3)
- AWS_SECRET_ACCESS_KEY (si usa S3)
IMPORTANTE - Cumplimiento Normativo:
- NOM-024-SSA3-2012: Logs de auditoria obligatorios
- Encriptacion de datos sensibles (historiales)
- Backups diarios con retencion minima 5 anos
diferencias:
- nombre: "NODE_ENV"
valor: "production"
- nombre: "LOG_LEVEL"
valor: "info"
- nombre: "LOG_FORMAT"
valor: "json"
- nombre: "DB_PORT"
valor: "5432"
- nombre: "REDIS_PORT"
valor: "6379"
- nombre: "STORAGE_TYPE"
valor: "s3"
- nombre: "AUDIT_ENABLED"
valor: "true"
- nombre: "DATA_ENCRYPTION"
valor: "true"
# -----------------------------------------------------------------------------
# CONTENEDORES DOCKER
# -----------------------------------------------------------------------------
docker:
compose_file: "docker-compose.yml"
compose_dev: "docker-compose.dev.yml"
compose_prod: "docker-compose.prod.yml"
services:
- nombre: "db"
imagen: "postgres:15-alpine"
puerto_host: 5441
puerto_container: 5432
variables:
POSTGRES_DB: "clinica_dental_dev"
POSTGRES_USER: "dental_dev"
POSTGRES_PASSWORD: "${DB_PASSWORD}"
volumes:
- "postgres_data:/var/lib/postgresql/data"
healthcheck: "pg_isready -U dental_dev"
- nombre: "redis"
imagen: "redis:7-alpine"
puerto_host: 6388
puerto_container: 6379
volumes:
- "redis_data:/data"
healthcheck: "redis-cli ping"
- nombre: "mailhog"
imagen: "mailhog/mailhog"
puerto_smtp: 1025
puerto_web: 8025
uso: "Testing de emails en desarrollo"
volumes:
- nombre: "postgres_data"
descripcion: "Datos persistentes de PostgreSQL"
- nombre: "redis_data"
descripcion: "Datos persistentes de Redis"
- nombre: "uploads_data"
descripcion: "Radiografias y documentos"
networks:
- nombre: "clinica_dental_network"
driver: "bridge"
# -----------------------------------------------------------------------------
# MIGRACIONES Y SEEDS
# -----------------------------------------------------------------------------
migraciones:
herramienta: "TypeORM"
directorio: "apps/backend/src/database/migrations"
comandos:
generar: "npm run migration:generate -- -n NombreMigracion"
ejecutar: "npm run migration:run"
revertir: "npm run migration:revert"
mostrar: "npm run migration:show"
seeds:
directorio: "database/seeds"
orden:
- "fase8/01-dental-catalogos.sql"
- "fase8/02-piezas-dentales-fdi.sql"
comandos:
ejecutar: "npm run seed"
desarrollo: "npm run seed:dev"
# -----------------------------------------------------------------------------
# SCRIPTS DE DESARROLLO
# -----------------------------------------------------------------------------
scripts:
setup:
descripcion: "Configurar entorno desde cero"
pasos:
- comando: "npm install"
descripcion: "Instalar dependencias"
- comando: "cp .env.example .env"
descripcion: "Crear archivo de configuracion"
- comando: "docker-compose up -d db redis"
descripcion: "Levantar servicios de infraestructura"
- comando: "npm run db:create"
descripcion: "Crear base de datos"
- comando: "npm run migration:run"
descripcion: "Ejecutar migraciones"
- comando: "npm run seed"
descripcion: "Cargar datos iniciales (incluye 52 piezas FDI)"
desarrollo:
frontend: "cd apps/frontend && npm run dev"
backend: "cd apps/backend && npm run start:dev"
ambos: "npm run dev:all"
docker: "docker-compose up -d"
testing:
unit: "npm run test"
unit_watch: "npm run test:watch"
e2e: "npm run test:e2e"
coverage: "npm run test:cov"
build:
frontend: "cd apps/frontend && npm run build"
backend: "cd apps/backend && npm run build"
docker: "docker-compose -f docker-compose.prod.yml build"
database:
create: "npm run db:create"
drop: "npm run db:drop"
reset: "npm run db:reset"
migrations_run: "npm run migration:run"
migrations_revert: "npm run migration:revert"
seed: "npm run seed"
linting:
lint: "npm run lint"
lint_fix: "npm run lint:fix"
format: "npm run format"
# -----------------------------------------------------------------------------
# INSTRUCCIONES DE SETUP
# -----------------------------------------------------------------------------
setup_instrucciones: |
## Setup del Entorno de Desarrollo - Clinica Dental
### Prerequisitos
- Node.js 20.x (LTS)
- PostgreSQL 15 (o Docker)
- Redis 7 (o Docker)
- npm 10.x
- Git
### Opcion 1: Setup con Docker (Recomendado)
```bash
# 1. Clonar repositorio
git clone <url_repo>
cd clinica-dental
# 2. Instalar dependencias
npm install
# 3. Configurar variables de entorno
cp .env.example .env
# Editar .env - generar passwords seguros:
# openssl rand -base64 32 # para DB_PASSWORD
# openssl rand -base64 64 # para JWT_SECRET
# 4. Levantar infraestructura
docker-compose up -d db redis
# 5. Crear base de datos y ejecutar migraciones
npm run db:create
npm run migration:run
npm run seed # Carga 52 piezas dentales FDI
# 6. Iniciar desarrollo
npm run dev:all
```
### Opcion 2: Setup con PostgreSQL Local
```bash
# 1-3. Igual que arriba
# 4. Crear usuario y base de datos en PostgreSQL
sudo -u postgres psql
CREATE USER dental_dev WITH PASSWORD 'tu_password';
CREATE DATABASE clinica_dental_dev OWNER dental_dev;
GRANT ALL PRIVILEGES ON DATABASE clinica_dental_dev TO dental_dev;
\q
# 5. Configurar Redis local o Docker
docker run -d --name redis-dental -p 6388:6379 redis:7-alpine
# 6-7. Continuar con migraciones y seeds
```
### Verificar Instalacion
- Frontend: http://localhost:3130
- Backend API: http://localhost:3131/api/v1
- Swagger Docs: http://localhost:3131/api/docs
- Health Check: http://localhost:3131/health
### Usuarios de Prueba (despues de seed)
- Admin: admin@clinica-dental.local / Admin123!
- Odontologo: doctor@clinica-dental.local / Doctor123!
- Recepcion: recepcion@clinica-dental.local / Recep123!
### Nomenclatura Dental FDI
El sistema usa la nomenclatura FDI (Federation Dentaire Internationale):
- Cuadrante 1: Superior derecho (18-11)
- Cuadrante 2: Superior izquierdo (21-28)
- Cuadrante 3: Inferior izquierdo (31-38)
- Cuadrante 4: Inferior derecho (41-48)
- Cuadrantes 5-8: Denticion temporal
# -----------------------------------------------------------------------------
# TROUBLESHOOTING
# -----------------------------------------------------------------------------
troubleshooting:
- problema: "Puerto 3130 o 3131 en uso"
solucion: |
Verificar con: lsof -i :3130
Terminar proceso: kill -9 <PID>
O cambiar puertos en .env
- problema: "Error de conexion a PostgreSQL"
solucion: |
1. Verificar que PostgreSQL esta corriendo:
docker-compose ps
# o: systemctl status postgresql
2. Verificar credenciales en .env
3. Verificar que la BD existe:
psql -h localhost -p 5441 -U dental_dev -l
- problema: "Error de conexion a Redis"
solucion: |
1. Verificar que Redis esta corriendo:
docker-compose ps
# o: redis-cli -p 6388 ping
2. Verificar puerto en .env
- problema: "Migraciones fallan"
solucion: |
1. Verificar que la BD existe
2. Verificar permisos del usuario
3. Revisar logs: npm run migration:run --verbose
4. Si es necesario, resetear: npm run db:reset
- problema: "Piezas dentales no cargadas"
solucion: |
Ejecutar seeds manualmente:
npm run seed
Verificar: SELECT COUNT(*) FROM dental.piezas_dentales;
Debe retornar 52 (32 permanentes + 20 temporales)
- problema: "Radiografias no se suben"
solucion: |
1. Verificar STORAGE_PATH existe y tiene permisos
2. Verificar MAX_FILE_SIZE en .env (default 20MB)
3. Verificar ALLOWED_FILE_TYPES incluye el tipo de archivo
- problema: "JWT errors"
solucion: |
Verificar que JWT_SECRET esta configurado (min 32 caracteres)
Generar nuevo: openssl rand -base64 64
- problema: "CORS errors en frontend"
solucion: |
Verificar FRONTEND_URL y ALLOWED_ORIGINS en .env
Deben coincidir con la URL del frontend
# -----------------------------------------------------------------------------
# CONFIGURACION DE PRODUCCION
# -----------------------------------------------------------------------------
produccion:
checklist:
- item: "Variables de entorno configuradas via secrets manager"
- item: "SSL/TLS habilitado para BD y Redis"
- item: "Backups automaticos configurados (retencion 5 anos)"
- item: "Monitoreo y alertas activas"
- item: "Rate limiting configurado"
- item: "CORS restringido a dominios autorizados"
- item: "Logs en formato JSON para agregacion"
- item: "Audit logging habilitado (NOM-024-SSA3-2012)"
- item: "Encriptacion de datos sensibles"
infraestructura_recomendada:
base_de_datos: "AWS RDS PostgreSQL 15 o equivalente"
cache: "AWS ElastiCache Redis o equivalente"
storage: "AWS S3 o equivalente (para radiografias)"
cdn: "CloudFront o equivalente"
ci_cd: "GitHub Actions / GitLab CI"
escalado:
backend_replicas: 2
pool_db_size: 50
redis_maxmemory: "512mb"
storage_bucket_region: "us-east-1"
cumplimiento:
nom_024_ssa3:
descripcion: "Expediente clinico electronico"
requisitos:
- "Logs de auditoria inmutables"
- "Firma electronica de expedientes"
- "Control de versiones de historiales"
retencion_datos:
expedientes: "5 anos minimo"
radiografias: "5 anos minimo"
logs_auditoria: "5 anos"
# -----------------------------------------------------------------------------
# REFERENCIAS
# -----------------------------------------------------------------------------
referencias:
perfil_devenv: "orchestration/agents/perfiles/PERFIL-DEVENV.md"
inventario_master: "orchestration/inventarios/DEVENV-MASTER-INVENTORY.yml"
inventario_puertos: "orchestration/inventarios/DEVENV-PORTS-INVENTORY.yml"
contexto_proyecto: "orchestration/00-guidelines/CONTEXTO-PROYECTO.md"
parent_clinicas: "../erp-clinicas/orchestration/environment/ENVIRONMENT-INVENTORY.yml"
schema_dental: "database/schemas/01-dental-schema-ddl.sql"
nomenclatura_fdi: "https://www.fdiworlddental.org/tooth-numbering-system"
# =============================================================================
# FIN DE INVENTARIO
# =============================================================================