Bilingual Navigation: English (this document) · Versión en Español
Document Status: Implemented (Waves 1-4)
Type: Implementation Report
Satellite: Evolith Tracker
Date: 2026-07-03
Author: Winston (System Architect) + Amelia (Senior Software Engineer)
This document records the platform architecture implementation completed in Waves 1-4, covering:
- Wave 1: Foundation & Configuration (shared infrastructure, domain primitives, web types)
- Wave 2: PostgreSQL & Core Entities (TypeORM, migrations, entities, repositories)
- Wave 3: Governance & Gate Decision Engine (domain, CQRS, controllers)
- Wave 4: Core Integration Hardening (circuit breaker, ACL, persistence)
The tracker-web application had three missing files that blocked compilation:
| File | Purpose |
|---|---|
src/apps/tracker-web/src/data/types.ts |
All TypeScript interfaces: Dataset, Phase, Tenant, Catalog, Core, Product, Initiative, Eval, Verdict, CoreEvaluationTransaction, etc. |
src/apps/tracker-web/src/data/crud.ts |
CRUD configuration registry mapping entity names to array keys, ID keys, prefixes, fields, and factories |
src/apps/tracker-web/src/utils/format.ts |
Utility functions: nextId() for sequential ID generation, stamp() for timestamps |
Decision: Types were inferred from usage patterns in tdata.ts, tracker.store.ts, and tracker-bff.client.ts.
Enhanced the existing domain library with framework-agnostic building blocks:
| File | Class/Interface | Purpose |
|---|---|---|
aggregates/entity.ts |
Entity<T> |
Base class with identity and equality |
aggregates/aggregate-root.ts |
AggregateRoot<T> |
Extends Entity with domain event collection |
value-objects/result.ts |
Result<T, TError> |
Monad for success/failure without exceptions |
events/domain-event.ts |
DomainEvent, BaseDomainEvent |
Event contract and abstract base |
events/event-bus.ts |
IDomainEventBus |
Port for event publishing/subscribing |
errors/domain.error.ts |
DomainError, NotFoundError, ConcurrencyError, ValidationError |
Domain error hierarchy |
ports/unit-of-work.ts |
IUnitOfWork |
Transaction boundary port |
ports/repository.ts |
IRepository<T> |
Generic repository port |
Rule enforced: Zero imports from NestJS, TypeORM, PostgreSQL, or any external SDK.
Created the cross-cutting infrastructure library:
| Component | File | Purpose |
|---|---|---|
| Config | config/config.module.ts |
NestJS ConfigModule wrapper with .env.local + .env |
| Database | database/database.module.ts |
TypeORM DataSource async setup via ConfigService |
| Redis | redis/redis.module.ts |
ioredis client with graceful null when REDIS_URL unset |
| Event Bus | messaging/domain-event-bus.ts |
In-memory IDomainEventBus implementation |
| Outbox | messaging/transactional-outbox.ts |
OutboxMessage entity + repository for at-least-once delivery |
| Outbox Processor | messaging/outbox-processor.ts |
Background cron processor with retry + error tracking |
| Cache | cache/redis-cache.service.ts |
Redis cache with TTL, null-safe when Redis unavailable |
| Idempotency | cache/idempotency.service.ts |
NX-based idempotency key store |
| Lock | lock/distributed-lock.service.ts |
Redis distributed lock with Lua-based release |
| Correlation ID | observability/correlation-id.interceptor.ts |
Extracts/propagates x-correlation-id |
| Logging | observability/logging.interceptor.ts |
Structured request logging with duration |
| Exception Filter | filters/global-exception.filter.ts |
RFC 9457 application/problem+json responses |
| Tenant Guard | guards/tenant.guard.ts |
Extracts x-tenant-id header, fail-closed |
| API Response | dto/api-response.dto.ts |
Standard { success, data, error, correlationId, timestamp } envelope |
Updated .env.example with all required variables:
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=| Package | Version | Purpose |
|---|---|---|
@nestjs/config |
^4.0.0 | Environment variable management |
@nestjs/typeorm |
^11.0.0 | TypeORM integration |
@nestjs/schedule |
^5.0.0 | Cron scheduling for outbox processor |
@nestjs/terminus |
^11.0.0 | Health checks |
@nestjs/throttler |
^6.0.0 | Rate limiting |
ioredis |
^5.6.0 | Redis client |
Created 7 migration files in src/apps/tracker-api/src/migrations/:
| Migration | Schemas/Tables | Key Features |
|---|---|---|
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 tables | satellite_products, sdlc_executions, phase_gate_states, exception_requests, outbox_messages |
0003-create-artifacts-tables.sql |
3 tables | artifact_definitions, artifact_instances, evidence_records |
0004-create-integration-tables.sql |
4 tables | core_evaluation_transactions, integration_endpoints, sync_records, acl_adapters |
0005-create-audit-table.sql |
1 table | audit_entries with append-only trigger (BEFORE UPDATE OR DELETE) |
0006-create-discovery-tables.sql |
4 tables | initiatives, backlogs, epics, user_stories |
0007-create-rls-policies.sql |
RLS | Row-Level Security on all tenant-scoped tables |
Common columns on every table: id (UUID PK), tenant_id, created_at, created_by, updated_at, updated_by, deleted_at, version.
| Entity | Schema | File |
|---|---|---|
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 |
| Repository | Entity | Context |
|---|---|---|
TypeOrmPhaseGateStateRepository |
PhaseGateStateEntity |
Governance |
TypeOrmCoreEvaluationTransactionRepository |
CoreEvaluationTransactionEntity |
Integration |
TypeOrmEvidenceRecordRepository |
EvidenceRecordEntity |
Artifacts |
TypeOrmInitiativeRepository |
InitiativeEntity |
Discovery |
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):
- Tracks current phase and status across the SDLC lifecycle
- Records gate decisions per phase
- Enforces phase advancement rules (must have approved gate to advance)
- Supports blocking/unblocking with reasons
| Handler | Type | Purpose |
|---|---|---|
CreateGateDecisionHandler |
Command | Creates a new GateDecision VO |
GetGateStatusHandler |
Query | Returns gate status for a specific phase |
ListGatesHandler |
Query | Lists all gate states for an execution |
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/gates |
List gate states |
GET |
/api/v1/gates/:gateId |
Get gate detail |
POST |
/api/v1/gates/:gateId/evaluate |
Trigger gate evaluation |
POST |
/api/v1/gates/:gateId/decision |
Make a gate decision (Tracker decides) |
GET |
/api/v1/evidence |
List evidence records |
POST |
/api/v1/evidence |
Create evidence record |
GET |
/api/v1/audit |
List audit entries (append-only) |
States: CLOSED → OPEN → HALF_OPEN → CLOSED
Failure threshold: 5 consecutive failures
Recovery time: 30 seconds
- CLOSED: Normal operation, requests pass through
- OPEN: All requests blocked for 30s after 5 failures
- HALF_OPEN: One test request allowed; success → CLOSED, failure → OPEN
Attempts: 3 (1 initial + 2 retries)
Backoff: 1s, 2s, 4s (capped at 5s)
Applies to: all Core API requests
CoreEvaluationAcl maps Core EvaluationVerdict → Tracker TrackerEvaluationResult:
Core EvaluationVerdict → CoreEvaluationAcl.mapVerdictToTrackerResult() → TrackerEvaluationResult
No raw Core schema leaks to the UI. The ACL is the single translation point.
Every request to Core includes x-correlation-id header, enabling end-to-end traceability from Browser → BFF → Core.
| ID | Decision | Rationale |
|---|---|---|
| T-026 | Redis for operational support only | Every critical state lands in PostgreSQL. Redis degrades gracefully. |
| T-027 | Circuit breaker on Core API client | Prevents cascade failures when Core is unavailable. |
| T-028 | Schema-per-context PostgreSQL strategy | Logical isolation without foreign keys between schemas. |
| T-029 | OpenTelemetry Collector as single telemetry sink | Decouples app from backend (Prometheus, Grafana, Loki). |
| T-030 | K8s overlays via Kustomize | Simpler for Phase 1; Helm chart later if needed. |
# 1. Install dependencies
cd src && npm install
# 2. Build tracker-api
npx nx build tracker-api
# 3. Build tracker-web
npx vite build --config apps/tracker-web/vite.config.mts
# 4. Start PostgreSQL (requires local instance or Docker)
# docker run -d --name tracker-pg -e POSTGRES_PASSWORD=localdev -e POSTGRES_DB=evolith_tracker -p 5432:5432 postgres:16
# 5. Run migrations
psql -h localhost -U evolith -d evolith_tracker -f apps/tracker-api/src/migrations/0001-create-schemas.sql
# ... repeat for 0002-0007
# 6. Start the API
npx nx serve tracker-api| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | — | PostgreSQL connection string |
REDIS_URL |
No | — | Redis URL (graceful degradation if missing) |
CORE_API_BASE_URL |
Yes | http://localhost:8000/api/v1 |
Core API gateway |
CORE_API_TIMEOUT_MS |
No | 8000 |
Core request timeout |
CORE_API_KEY |
No | — | Server-side API key for Core |
TRACKER_WEB_ORIGIN |
Yes | http://localhost:4200 |
CORS origin |
OTEL_EXPORTER_OTLP_ENDPOINT |
No | http://localhost:4318 |
OpenTelemetry collector |
UMS_JWKS_URI |
No | — | UMS JWKS endpoint |
JWT_SECRET |
No | — | JWT signing secret |
| Gap | Wave | Status |
|---|---|---|
| OpenTelemetry + Grafana/Prometheus | Wave 5 | Deferred |
| Docker + Kubernetes manifests | Wave 6 | Deferred |
| Security hardening (JWT, rate limiting) | Wave 7 | Deferred |
| Tests + Web BFF integration | Wave 8 | Deferred |
| UMS Authorization Graph | Future | Not started |
| Full DDD contexts (Design, Construction, QA, Release) | Future | Not started |
CLI (evolith) |
Future | Not started |
| MCP server | Future | Not started |
- Tracker Target Architecture — Primary TAD
- NestJS Backend Design — Backend design spec
- PostgreSQL Data Design — Data architecture
- Core Integration Design — Integration spec
- ADR-0002: Clean Hexagonal Architecture
- ADR-0043: ORM Strategy