Navegación Bilingüe: English (este documento) · English
Estado del Documento: Implementado (Ondas 1-4)
Tipo: Reporte de Implementación
Satélite: Evolith Tracker
Fecha: 2026-07-03
Autor: Winston (Arquitecto de Sistemas) + Amelia (Ingeniera de Software Senior)
Este documento registra la implementación de la arquitectura de la plataforma completada en las Ondas 1-4:
- Onda 1: Fundación y Configuración (infraestructura compartida, primitivas de dominio, tipos web)
- Onda 2: PostgreSQL y Entidades Core (TypeORM, migraciones, entidades, repositorios)
- Onda 3: Motor de Gobernanza y Decisiones de Gate (dominio, CQRS, controladores)
- Onda 4: Endurecimiento de Integración con Core (circuit breaker, ACL, persistencia)
La aplicación tracker-web tenía tres archivos faltantes que bloqueaban la compilación:
| Archivo | Propósito |
|---|---|
src/apps/tracker-web/src/data/types.ts |
Todas las interfaces TypeScript: Dataset, Phase, Tenant, Catalog, Core, Product, Initiative, Eval, Verdict, CoreEvaluationTransaction, etc. |
src/apps/tracker-web/src/data/crud.ts |
Registro de configuración CRUD mapeando nombres de entidades a claves de arreglo, claves ID, prefijos, campos y fábricas |
src/apps/tracker-web/src/utils/format.ts |
Funciones utilitarias: nextId() para generación de ID secuencial, stamp() para marcas de tiempo |
Decisión: Los tipos se infirieron de patrones de uso en tdata.ts, tracker.store.ts y tracker-bff.client.ts.
Se mejoró la biblioteca de dominio existente con bloques de construcción framework-agnósticos:
| Archivo | Clase/Interfaz | Propósito |
|---|---|---|
aggregates/entity.ts |
Entity<T> |
Clase base con identidad e igualdad |
aggregates/aggregate-root.ts |
AggregateRoot<T> |
Extiende Entity con colección de eventos de dominio |
value-objects/result.ts |
Result<T, TError> |
Monad para éxito/fallo sin excepciones |
events/domain-event.ts |
DomainEvent, BaseDomainEvent |
Contrato de evento y base abstracta |
events/event-bus.ts |
IDomainEventBus |
Puerto para publicación/suscripción de eventos |
errors/domain.error.ts |
DomainError, NotFoundError, ConcurrencyError, ValidationError |
Jerarquía de errores de dominio |
ports/unit-of-work.ts |
IUnitOfWork |
Puerto de límite transaccional |
ports/repository.ts |
IRepository<T> |
Puerto de repositorio genérico |
Regla enforced: Cero imports de NestJS, TypeORM, PostgreSQL o cualquier SDK externo.
Se creó la biblioteca de infraestructura transversal:
| Componente | Archivo | Propósito |
|---|---|---|
| Config | config/config.module.ts |
Wrapper de NestJS ConfigModule con .env.local + .env |
| Database | database/database.module.ts |
Configuración async de TypeORM DataSource via ConfigService |
| Redis | redis/redis.module.ts |
Cliente ioredis con null gracefully cuando REDIS_URL no está configurado |
| Event Bus | messaging/domain-event-bus.ts |
Implementación in-memory de IDomainEventBus |
| Outbox | messaging/transactional-outbox.ts |
Entidad OutboxMessage + repositorio para entrega at-least-once |
| Procesador Outbox | messaging/outbox-processor.ts |
Procesador cron en segundo plano con retry + tracking de errores |
| Cache | cache/redis-cache.service.ts |
Cache Redis con TTL, null-safe cuando Redis no está disponible |
| Idempotency | cache/idempotency.service.ts |
Almacén de claves de idempotencia basado en NX |
| Lock | lock/distributed-lock.service.ts |
Lock distribuido Redis con release basado en Lua |
| Correlation ID | observability/correlation-id.interceptor.ts |
Extrae/propaga x-correlation-id |
| Logging | observability/logging.interceptor.ts |
Logging estructurado de requests con duración |
| Filtro Excepción | filters/global-exception.filter.ts |
Respuestas RFC 9457 application/problem+json |
| Guard Tenant | guards/tenant.guard.ts |
Extrae header x-tenant-id, fail-closed |
| API Response | dto/api-response.dto.ts |
Envelope estándar { success, data, error, correlationId, timestamp } |
Se actualizó .env.example con todas las variables requeridas:
DATABASE_URL=postgresql://evolith:localdev@localhost:5432/evolith_tracker
REDIS_URL=redis://localhost:6379
CORE_API_BASE_URL=http://localhost:8000/api/v1
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
UMS_JWKS_URI=
JWT_SECRET=| Paquete | Versión | Propósito |
|---|---|---|
@nestjs/config |
^4.0.0 | Gestión de variables de entorno |
@nestjs/typeorm |
^11.0.0 | Integración TypeORM |
@nestjs/schedule |
^5.0.0 | Programación cron para procesador outbox |
@nestjs/terminus |
^11.0.0 | Health checks |
@nestjs/throttler |
^6.0.0 | Rate limiting |
ioredis |
^5.6.0 | Cliente Redis |
Se crearon 7 archivos de migración en src/apps/tracker-api/src/migrations/:
| Migración | Schemas/Tablas | Características Clave |
|---|---|---|
0001-create-schemas.sql |
10 schemas | tracker_discovery, tracker_design, tracker_construction, tracker_qa, tracker_release, tracker_governance, tracker_artifacts, tracker_metrics, tracker_integration, tracker_audit |
0002-create-governance-tables.sql |
5 tablas | satellite_products, sdlc_executions, phase_gate_states, exception_requests, outbox_messages |
0003-create-artifacts-tables.sql |
3 tablas | artifact_definitions, artifact_instances, evidence_records |
0004-create-integration-tables.sql |
4 tablas | core_evaluation_transactions, integration_endpoints, sync_records, acl_adapters |
0005-create-audit-table.sql |
1 tabla | audit_entries con trigger append-only (BEFORE UPDATE OR DELETE) |
0006-create-discovery-tables.sql |
4 tablas | initiatives, backlogs, epics, user_stories |
0007-create-rls-policies.sql |
RLS | Row-Level Security en todas las tablas con tenant |
Columnas comunes en todas las tablas: id (UUID PK), tenant_id, created_at, created_by, updated_at, updated_by, deleted_at, version.
| Entidad | Schema | Archivo |
|---|---|---|
PhaseGateStateEntity |
tracker_governance |
libs/governance/src/lib/infrastructure/persistence/entities/phase-gate-state.entity.ts |
CoreEvaluationTransactionEntity |
tracker_integration |
apps/tracker-api/src/app/integration/entities/core-evaluation-transaction.entity.ts |
EvidenceRecordEntity |
tracker_artifacts |
libs/artifacts/src/lib/infrastructure/persistence/entities/evidence-record.entity.ts |
AuditEntryEntity |
tracker_audit |
libs/audit/src/lib/infrastructure/persistence/entities/audit-entry.entity.ts |
InitiativeEntity |
tracker_discovery |
libs/discovery/src/infrastructure/persistence/entities/initiative.entity.ts |
GateDecision (Value Object):
class GateDecision {
id: string;
tenantId: string;
sdlcExecutionId: string;
phase: string;
gateStatus: string;
decisionBy: string;
decidedAt: Date;
rationale: string;
evaluationIds: string[];
status: 'approved' | 'rejected' | 'approved_with_exception' | 'pending' | 'blocked';
}SDLCExecution (Aggregate Root):
- Rastrea fase actual y estado a través del ciclo de vida SDLC
- Registra decisiones de gate por fase
- Enforce reglas de avance de fase (debe tener gate aprobado para avanzar)
- Soporta bloqueo/desbloqueo con razones
| Método | Ruta | Descripción |
|---|---|---|
GET |
/api/v1/gates |
Listar estados de gate |
GET |
/api/v1/gates/:gateId |
Obtener detalle de gate |
POST |
/api/v1/gates/:gateId/evaluate |
Trigger evaluación de gate |
POST |
/api/v1/gates/:gateId/decision |
Tomar decisión de gate (Tracker decide) |
GET |
/api/v1/evidence |
Listar registros de evidencia |
POST |
/api/v1/evidence |
Crear registro de evidencia |
GET |
/api/v1/audit |
Listar entradas de auditoría (append-only) |
Estados: CLOSED → OPEN → HALF_OPEN → CLOSED
Umbral de fallo: 5 fallos consecutivos
Tiempo de recuperación: 30 segundosCoreEvaluationAcl mapea EvaluationVerdict de Core → TrackerEvaluationResult:
Ningún esquema crudo de Core se filtra al UI. La ACL es el único punto de traducción.
| ID | Decisión | Justificación |
|---|---|---|
| T-026 | Redis solo para soporte operacional | Todo estado crítico va a PostgreSQL. Redis degrada gracefully. |
| T-027 | Circuit breaker en cliente Core API | Previene fallos en cascada cuando Core no está disponible. |
| T-028 | Estrategia PostgreSQL schema-per-context | Aislamiento lógico sin foreign keys entre schemas. |
| T-029 | OpenTelemetry Collector como sink único | Desacopla la app del backend (Prometheus, Grafana, Loki). |
| T-030 | K8s overlays via Kustomize | Más simple para Fase 1; Helm chart después si se necesita. |
# 1. Instalar dependencias
cd src && npm install
# 2. Compilar tracker-api
npx nx build tracker-api
# 3. Compilar tracker-web
npx vite build --config apps/tracker-web/vite.config.mts
# 4. Iniciar PostgreSQL (requiere instancia local o Docker)
# docker run -d --name tracker-pg -e POSTGRES_PASSWORD=localdev -e POSTGRES_DB=evolith_tracker -p 5432:5432 postgres:16
# 5. Ejecutar migraciones
psql -h localhost -U evolith -d evolith_tracker -f apps/tracker-api/src/migrations/0001-create-schemas.sql
# ... repetir para 0002-0007
# 6. Iniciar la API
npx nx serve tracker-api| Brecha | Onda | Estado |
|---|---|---|
| OpenTelemetry + Grafana/Prometheus | Onda 5 | Diferido |
| Docker + manifests Kubernetes | Onda 6 | Diferido |
| Endurecimiento de seguridad (JWT, rate limiting) | Onda 7 | Diferido |
| Tests + integración Web BFF | Onda 8 | Diferido |
| Grafo de Autorización UMS | Futuro | No iniciado |
| Contextos DDD completos (Design, Construction, QA, Release) | Futuro | No iniciado |
CLI (evolith) |
Futuro | No iniciado |
| Servidor MCP | Futuro | No iniciado |
- Arquitectura Objetivo del Tracker — TAD principal
- Diseño Backend NestJS — Especificación de diseño backend
- Diseño de Datos PostgreSQL — Arquitectura de datos
- Diseño de Integración Core — Especificación de integración