Skip to content

Latest commit

 

History

History
304 lines (227 loc) · 13 KB

File metadata and controls

304 lines (227 loc) · 13 KB

Evolith Tracker — Platform Architecture Implementation

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)


1. Implementation Overview

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)

2. What Was Implemented

2.1 Wave 1 — Foundation

2.1.1 Missing Web Types (Critical Fix)

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.

2.1.2 Shared Domain Primitives (libs/domain)

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.

2.1.3 Shared Infrastructure Module (libs/shared)

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

2.1.4 Environment Overlays

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=

2.1.5 Dependencies Added

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

2.2 Wave 2 — PostgreSQL & Core Entities

2.2.1 SQL Migrations

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.

2.2.2 TypeORM Entities

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

2.2.3 Repositories

Repository Entity Context
TypeOrmPhaseGateStateRepository PhaseGateStateEntity Governance
TypeOrmCoreEvaluationTransactionRepository CoreEvaluationTransactionEntity Integration
TypeOrmEvidenceRecordRepository EvidenceRecordEntity Artifacts
TypeOrmInitiativeRepository InitiativeEntity Discovery

2.3 Wave 3 — Governance & Gate Decision Engine

2.3.1 Domain Model

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

2.3.2 CQRS Handlers

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

2.3.3 API Endpoints

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)

2.4 Wave 4 — Core Integration Hardening

2.4.1 Circuit Breaker

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

2.4.2 Retry with Exponential Backoff

Attempts: 3 (1 initial + 2 retries)
Backoff: 1s, 2s, 4s (capped at 5s)
Applies to: all Core API requests

2.4.3 Anti-Corruption Layer (ACL)

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.

2.4.4 Correlation ID Propagation

Every request to Core includes x-correlation-id header, enabling end-to-end traceability from Browser → BFF → Core.


3. Architecture Decisions Registered

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.

4. How to Run Locally

# 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

5. Environment Variables

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

6. Remaining Gaps (Waves 5-8)

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

References