| title | Registro de Decisiones Arquitectónicas Locales |
|---|---|
| type | hub |
| classification | Product ADR |
| owner | Evolith Tracker Team |
Bilingual Navigation: English (this document) · Versión en Español
Este documento sirve como el Hub de Decisiones Arquitectónicas Locales para Evolith Tracker. Documenta las decisiones y desviaciones específicas de este producto satélite frente al Core.
Nota: Las decisiones universales se heredan del Upstream Base (evolith_arch32).
- Upstream base:
https://github.com/beyondnetcode/evolith_arch32 - Última clasificación:
2026-06-28 - Convención de IDs de ADR upstream: calificados por categoría —
core/,nodejs/,dotnet/,android/(p. ej.core/0074,nodejs/0075). - ADRs locales (satélite): este repositorio es un satélite gobernado — ver
evolith.yaml. Los ADRs locales conservan su namespaceT-{NNN}(distinto delADR-{NNNN}del Core, per T-011), siguen la plantilla canónica de 6 secciones del Core, llevan el tagEvolithSatelliteen su frontmatter y están registrados enevolith.yaml → spec.compliance.adrRegistry(regla federada CoreINH-04). - Fuente única de verdad (CD-18): el fichero
docs/adrs/T-{NNN}-<slug>.md(+ su par.es.md) es el ADR; los demás registros son índices derivados que deben mantenerse en sincronía con él y con el disco: (1) este hub (DECISIONS.md/.es.md), (2)evolith.yaml → spec.compliance.adrRegistry, y (3) el catálogo servido porGET /api/architecture/adrs(AdrRegistryCatalog). Al añadir o cambiar un ADR se actualizan los tres, y todo fichero dedocs/adrs/debe tener par bilingüe — comprobado porcheck-bilingual-parity.mjs(cobertura ADR).
| ID | Título | Operación | Ref Upstream | ADR Local | Notas |
|---|---|---|---|---|---|
| T-001 | Orquestación de Monorepo con Nx | Adoptar | ADR-0001 | — | Inicializado en src/ utilizando npm workspaces con Nx. |
| T-002 | Adopción de Microfrontends en Fase 1 | Sobrescribir | N/A | T-002 | Desviación de topología para escalabilidad de UI. |
| T-003 | Arquitectura Hexagonal (Ports & Adapters) | Adoptar | ADR-0002 | — | Capa de dominio pura sin dependencias externas. |
| T-004 | TypeScript estricto como lenguaje primario | Adoptar | ADR-0003 | — | strict: true habilitado. |
| T-005 | TypeORM como ORM (Data Mapper pattern) | Adoptar | ADR-0043 | — | Data Mapper elegido sobre Active Record. |
| T-006 | React con Vite como base del frontend | Adoptar | ADR-0044 | T-006 | Topología microfrontends. |
| T-007 | Zustand + TanStack Query (State Management) | Adoptar | ADR-0045 | — | Zustand (cliente) + TanStack Query (servidor). |
| T-008 | Convención de nombres de schema PostgreSQL | Definir | N/A | T-008 | Canónico: tracker_discovery, tracker_design... |
| T-009 | REST + OpenAPI 3.0 como única API en Fase 1 | Definir | N/A | T-009 | GraphQL fuera de alcance en Fase 1. |
| T-010 | Framework de agentes configurable por tenant | Extender | N/A | T-010 | Core usa BMAD internamente; el Tracker es framework-agnóstico. El tenant configura su harness agéntico por fase (bmad, spec-kit, custom). |
| T-011 | Estándar de numeración para Iniciativas, ADRs y Specs | Definir | N/A | T-011 | IDs de gobernanza/diseño: Iniciativas INIT-{NNN}, ADRs locales T-{NNN}, ADRs upstream ADR-{NNNN}. La descomposición de ejecución queda fuera de alcance. |
| T-012 | Contratos de eventos de dominio en libs/shared/ | Definir | N/A | — | Eventos compartidos (DriftDetectedEvent, ExternalCheckpointRegisteredEvent) se definen como contratos TypeScript en libs/shared/src/domain/events/. Pact tests pendientes (Phase 0). |
| T-013 | Value Object canónico ExternalReference en Shared Kernel | Definir | N/A | — | Unifica shapes dispares en 6 contextos. ExternalReference con system, externalId, url, type, linkedAt, label, metadata. Ubicado en libs/shared/src/domain/external-reference.vo.ts. |
| T-014 | UC-005 dividido en UC-005a y UC-005b | Definir | N/A | — | Plan Release y Authorize Deployment son operaciones distintas con distintos actores y precondiciones. UC-005a (Planning), UC-005b (Execution). |
| T-015 | Core BFF Gateway como único canal de comunicación | Adoptar | core/0074, nodejs/0075, core/0080 | — | El Tracker se comunica exclusivamente con Evolith Core a través del BFF Gateway (NestJS). Se prohíben llamadas directas a servicios internos de Core. Actualizado 2026-06-28 (CR-26): la nota previa "B2B API Gateway (API key)" queda obsoleta — core/0075 (api-key) fue superado por core/0080: Core no autentica; el BFF es el único perímetro (UMS Bearer + grafo de autorización) y las llamadas a Core usan repositoryRef+workspaceRef, sin API key. |
| T-016 | Capa Anti-Corrupción para Integración PPM (Funnel 0) | Definir | N/A | — | Se implementa una ACL (PpmIntakeACL) en el módulo tracker_intake para mapear y normalizar los esquemas de herramientas PPM externas (ej. Meisterplan) antes de que toquen el dominio del Tracker. Esto evita la contaminación de modelos financieros externos en el core del Tracker. |
| T-017 | Core API Exposure Layer (REST-only) | Adoptar | core/0074 | — | (CR-01/CR-02) Core-API es REST-only bajo /api/v1 (sin GraphQL/SSE) + gateway MCP. Salidas con envelope ADR-0073; errores RFC 9457. Reemplaza supuestos de transporte previos. |
| T-018 | Contrato de Referencia de Repositorio Remoto | Adoptar | core/0080 | — | (CR-26) Supera core/0075 (api-key). Core no autentica; el BFF es el único perímetro (UMS Bearer). Llamadas con contenido: repositoryRef {url, revision} + workspaceRef opaco + operationId. |
| T-019 | Separación Dominio/Financiero | Adoptar | core/0078 | — | (CR-17) ROI/finanzas fuera del dominio de gobernanza. Revisar Discovery Canvas / Business Case (hoy embeben ROI). |
| T-020 | Corpus Multi-Topología Componible | Adoptar | core/0079 | — | (CR-08/CR-09) Topología = 5 dimensiones componibles (progressive-axis/execution/integration/data/ai), no un ladder mono→micro. F1/F2/F3 = madurez de progressive-axis (modular-monolith/distributed-modules/microservices), no fases SDLC. |
| T-021 | PhaseId Canónico Semántico | Adoptar | core (GT-343) | — | (CR-28) Ids canónicos discovery|design|construction|qa|release; f1..f5 son alias deprecados solo de entrada; el namespace F# es madurez de topología. |
| T-022 | Contrato de Evaluación de Satélite | Adoptar | core/0073, core/0074 | — | (CR-03) POST /api/v1/evaluate → EvaluationVerdict (OPA real vía SatelliteEvaluationPipeline). El verdict es evidencia técnica, no un GateDecision canónico: el Tracker decide el gate. |
| T-023 | Distribución OPA-wasm Agnóstica | Adoptar | core/0085 | — | (CR-03) Evaluación de reglas vía rulesets/opa/policy.wasm; resultado por regla passed|failed|skipped (skipped si falta el wasm — manejar con gracia). |
| T-024 | Colisión de Nombre GateDecision |
Definir | Accepted | T-024 | (CR-12/CR-13) Core ya define un VO GateDecision (estrecho). El GateDecision canónico del Tracker (rico: status/snapshots/approvals/exceptions) se renombra/namespacea (p. ej. TrackerGateDecision) y mapea el VO de Core como entrada de TechnicalEvaluation. |
| T-025 | Gobernanza de IA Agéntica (cluster) | Referenciar | core/0081–0083, 0086–0089 | — | (CR-21/CR-27) Sandbox isolation, trust boundary, action-authorization audit, telemetry/cost, ABAC tool execution, sovereign identity, event-driven workflows. Base para la superficie "AI Governance" del Tracker. |
| T-026 | Redis solo para soporte operacional | Definir | N/A | — | Redis es cache/locks/jobs/idempotency. Todo estado crítico va a PostgreSQL. Redis degrada gracefully cuando no está disponible. No es system of record. |
| T-027 | Circuit breaker en cliente Core API | Definir | N/A | — | Estado machine CLOSED→OPEN→HALF_OPEN. Umbral: 5 fallos. Recuperación: 30s. Previene cascade failures cuando Core no está disponible. |
| T-028 | Estrategia PostgreSQL schema-per-context | Superado por T-047 | T-008 | — | Declaraba 10 schemas. El código creó 4 y nadie lo escribió, así que el registro decía una cosa y la base otra. T-047 ratifica la topología consolidada. |
| T-029 | OpenTelemetry Collector como sink único | Superado por T-049 | N/A | — | Desacopla la app del backend de observability (Prometheus, Grafana, Loki). Un solo endpoint OTLP. |
| T-030 | Superseded por T-043 | N/A | — | CD-29): la implementación eligió Helm y nunca hubo Kustomize — existen tres charts (product/infra/helm/evolith-tracker-{api,web,postgres}/Chart.yaml) y cero ficheros kustomization* en el repo. La decisión llevaba meses tomada en el código sin registro escrito; ver T-043. |
|
| T-031 | Criterios de evaluación de compuertas configurables por tenant sobre campos de artefactos | Definir | Accepted | T-031 | Base de artefactos autoritativa del Core (requeridos inmutables + opcionales) + overlay del tenant por compuerta: criterios por campo/valor, campos custom, config obligatoria (fail-closed con UNCONFIGURED), 5 estados de resultado (MET/NOT_MET/PENDING/OBSERVED/NOT_APPLICABLE) y traza total por criterio. |
| T-032 | Contexto acotado Geo / Datos Maestros (regionalización, localización, ubigeo) | Definir | Accepted | T-032 | Reemplaza los campos regionales libres (TenantLocalization) por catálogos maestros validados. Contexto geo dentro del Tracker con esquema propio + puerto IMasterDataDirectory + referencia blanda (geoId+snapshot); jerarquía por adyacencia+ltree, maestros globales tenant-agnósticos + overlays por tenant, datos por catalog_release. Extraíble a un servicio compartido evolith_mms (estrangulador) cuando exista un 2º consumidor. |
| T-033 | Adopción de la Plataforma Shell del Core (Ddd/Aop/Factory/Bootstrapper) | Adoptar | Accepted | T-033 | El dominio consume BeyondNetCode.Shell.Ddd (kernel compartido) en vez de un kernel propio; stack Shell completo (aspectos, factory, bootstrapper) espejando UMS. Cierra R-10 / Core ADR-0071. |
| T-034 | Hub de Configuración vs Monitor | Definir | Active | T-034 | La configuración/mantenimiento (CRUD) vive en Tenant configuration; los monitores son solo-lectura + comandos declarados por historias. §2.1 los registros están exentos; §2.2 toda sección de config es colapsable. |
| T-035 | Estándar de info-hints de campo (ayuda en contexto) | Definir | Active | T-035 | Todo término técnico/campo avanzado lleva un ⓘ InfoHint junto al label (significado·impacto·cuándo); info prop en TextField/Select, accesible, copy bilingüe. |
| T-036 | Parametrización de gates dirigida por artefactos del Core | Definir | Active | T-036 | (Extiende T-031) Evidencia y criterios anclados a artefactos definidos por el Core por fase (no texto libre); requerido efectivo = coreRequired OR tenantOverride; sin artefactos Core ⇒ sin criterios; GateMode (SIMPLE/COMPLEX) derivado de la config, no editable. |
| T-037 | Consumir la proyección de Tenant de MMS (Tracker como consumidor downstream) | Adoptar | Proposed | T-037 | Adopta Core ADR-0106 por referencia: MMS es la única autoridad del Tenant maestro. Tracker añade mensajería (MassTransit/RabbitMQ + inbox EF), consume TenantEvent con upsert versionado idempotente y degrada el agregado Tenant local a proyección de solo lectura. |
| T-038 | Binding a los contratos del Core vía schema neutro, no copia traducida a mano | Definir | Accepted | T-038 | @beyondnet/evolith-contracts es TypeScript-only e inconsumible desde .NET. Se pide a Core publicar JSON Schema de sus formas de cara al consumidor y se generan los tipos C# desde ahí. Puente provisional: DTOs derivados a mano confinados a la frontera de adaptador + guard de conformidad que falle el CI ante deriva (hoy es un no-op) + chequeo de schemaVersion en arranque. Cierra CD-12; prerrequisitos CD-01/CD-02. |
| T-039 | El Core recomienda, el tenant decide — la autoridad de excepción vive en el Tracker | Definir | Accepted | T-039 | Todo veredicto del Core (incluido un waiver aplicado upstream) es advisory: nunca satisface por sí solo un criterio de compuerta. La autoridad de excepción es del tenant y se ejerce en el Tracker. Exception pasa a agregado de primera clase con solicitante/autorizador/alcance/caducidad/revocación; GatePolicy separa approvalAuthority de waiverAuthority (default: autorizador distinto). Corolario: un veredicto MockFallback tampoco puede satisfacer una compuerta y se marca como sintético. Cierra CD-19/CD-20/CD-21. |
| T-040 | Adoptar el contrato de identidad de UMS v1 en vez de mantener un modelo propio | Adoptar | Accepted | T-040 | Tracker delega authn/authz en UMS, que es quien posee la abstracción de IdP (UMS ADR-0020): elegir IdP no es decisión de este satélite. UMS publica en 1.0.0 Ums.Sdk.Contracts/Authorization/.AspNetCore y Tracker es .NET, así que son consumibles directamente — pero no están publicados (sin dotnet pack/nuget push, 404 en nuget.org), de modo que la publicación es dependencia del board de UMS. Prohibido vendorizar o copiar a mano. Entregable inmediato y sin dependencia: alinear el claim de tenant a tid (UMS TE-01) y decidir el tratamiento de bid/cat/idp/jti. La reconciliación del modelo de permisos va aparte en CD-25. |
| T-041 | Línea base heredada: triaje y registro de los ADR del Core core/0090–core/0113 |
Referenciar | core/0090–0113 | T-041 | (CD-16) Los 24 ADRs del rango, triados con motivo escrito en cinco cubos. Gobiernan código ya embarcado: core/0101 (Core stateless), core/0102 (agent runtime, ya consumido), core/0106 (proyección de Tenant), core/0107 (clúster único), core/0108 (topología de mensajes), core/0109 (satélites monorepo), core/0110 (pin MassTransit v8) → alta en evolith.yaml → adrRegistry. Gobierna con brecha abierta: core/0091 (rotación de tokens de workload) — el Tracker usa claves estáticas, así que se declara en governingAdrs pero no en adrRegistry, para no afirmar un cumplimiento inexistente. Gobiernan trabajo planificado: core/0098, 0100, 0103, 0104, 0105, 0111, 0113. No aplicables (9, con motivo): core/0090, 0092–0094, 0095–0097, 0099, 0112. Heredar no es autoría: todos siguen siendo decisiones del Core. |
| T-042 | Guarda de build para el pin de licencia de MassTransit v8 | Definir | core/0110 | T-042 | (CD-16) MassTransit v9 es comercial y no sublicenciable; core/0110 fija la suite en v8 (Apache-2.0) y el Tracker cumplía por accidente con versiones exactas 8.3.1. Decisión local: rango acotado [8.3.1,9.0.0) en los tres PackageReference + guarda MSBuild solución-wide (src/apps/tracker-api/Directory.Build.targets, error EVOLITH0110) que falla el build si alguien reescribe la versión a mano. El modo de fallo que cierra no es un build roto, sino un build en verde embarcando licencia no redistribuible. Ampliar el rango exige superseder antes core/0110. |
| T-043 | Helm supersede a Kustomize como formato de orquestación K8s | Definir | Accepted | T-043 | Supersede T-030. Ratifica una decisión ya tomada en el código y jamás registrada: tres charts Helm (product/infra/helm/) son los únicos artefactos desplegables y no existe ningún kustomization*. Alcance limitado al formato de empaquetado; no decide GitOps, gestión de secretos ni destino de despliegue. Cierra la premisa falsa que ARCHITECTURE_REVIEW.md (:155, :696, :714) inyectó en el board vía AR-03 (CD-29). |
| T-044 | Un solo modelo de aislamiento entre tenants, con TenantScope como autoridad |
Definir | Accepted | T-044 | Hay TRES implementaciones de la misma regla (aspecto, TenantScope, filtro EF). El fallo-abierto que las hacía peligrosas se cerró en SEC-01; lo que queda es incoherencia funcional. Requiere ratificación del PO: alinear el aspecto con TenantScope amplía lo que un operador de plataforma alcanza en tenant-intelligence, y eso es decisión de producto, no técnica. |
| T-045 | Frontera de conectores: el Core posee la forma canónica; el Tracker posee conexión, credencial, fetch y sync | Definir | Accepted | T-045 | Verificado en el repositorio del Core: sus tres formas canónicas se declaran PURE y excluyen el fetch como paso de conector, y authorizesPhaseTransition: false está horneado en el tipo. Sin esta frontera el Tracker re-derivaría en .NET un mapeo ya canonizado, y el día que divergieran ganaría la copia local. Reduce el alcance de EAG-18/19/20/22 a la vez. |
| T-046 | El Tracker habla REST con el Core mediante cliente propio tipado; el SDK publicado es sólo Node | Definir | Accepted | T-046 | @evolith/sdk-client nunca existió —verificado contra npm— y el SDK real es una librería Node que un backend .NET no puede consumir en proceso. El cliente propio no es un apaño: es el binding correcto. Cierra CR-05. |
| T-047 | Topología de esquemas consolidada: 4 schemas, una convención, una excepción declarada | Adoptar | Accepted | T-047 | Supera a T-028. Ratifica los 4 schemas reales, renombra geo→tracker_geo, y declara masterdata como excepción CON MOTIVO: no es un contexto del Tracker sino una réplica de MMS. Cierra COH-015. |
| T-048 | Contrato de evidencia de señal de calidad: mapeo, semántica y quién la produce | Adoptar | Accepted | T-048 | Cierra CD-07, CD-08 y CD-09 como una sola conversación. dimension y determinism pasan a columna; metrics/findings[] se proyectan. La señal es advisory en el cable y exigible por GatePolicy. El Tracker NO ejecuta productores — eso es del agent-runtime (ADR-0111). |
| T-049 | Transporte de observabilidad: scrape Prometheus para métricas, push OTLP para trazas | Adoptar | Accepted | T-049 | Supera a T-029, que estaba en Definir SIN ADR — un boceto sin ratificar, no una decisión incumplida. Las trazas no tienen alternativa a push; las métricas siguen tirándose para no atar la disponibilidad del producto a la de un sumidero de telemetría. Exportador OTLP apagado por defecto. Cierra AR-14. |
| T-050 | Taxonomía del dominio: cinco fases, una maquinaria, una frontera, un resultado y unos cimientos | Adoptar | Accepted | T-050 | Sustituye el listado de «9 bounded contexts pares», que nunca describió este producto: Gobernanza sola tiene 8 agregados frente a 3 de las cinco fases juntas, y cinco contextos construidos (Tenancy, Products, Intake, Audit, Geo) no figuraban en él. Integración es FRONTERA bidireccional, no resultado; Sdlc (la vía) y Governance (el árbitro) siguen separados porque T-031 explota esa distinción. Parte AR-05 en vocabulario de fase (mejora sobre lo que ya funciona en genérico) y capa de resultado (Metrics, inexistente). |
| T-051 | El gateway MCP se enlaza al BFF del tracker-api, no al Core | Definir | Superseded | T-051 | Superado por T-052. Corrigió que las 6 tools MCP del Tracker tiraran de rutas imaginadas del Core, enlazándolas al BFF; su sujeto (el servidor MCP del Tracker) se eliminó después. |
| T-052 | Un solo MCP del ecosistema (el del Core); el gateway consume, no compite | Definir | Accepted | T-052 | Elimina el servidor MCP del Tracker; el gateway es BFF agregador que consume core-api (REST) y evolith-mcp (cliente). Supera a T-051. Verificado en vivo. |
| T-053 | Consumir la identidad UMS: JWKS/OIDC preferido, simétrico como interino | Definir | Proposed | T-053 | El tracker-api valida OIDC/JWKS pero el UMS no lo expone. Preferir que el UMS publique JWKS (aguas arriba); interino simétrico implementado y verificado con mock. |
| T-054 | Gate de frontera en tiempo de edición: adoptar acotado, diferido a EAG-11 | Definir | Accepted | T-054 | Adopta el edit-gate del Core pero DIFERIDO: .claude/ está en .gitignore, EAG-11 aún no da la fuente única de reglas, y el matcher puede misfirear. Activación condicionada a EAG-11 + versionar .claude/settings.json + acotar rutas + vía de escape. |
Plantilla para nuevos ADRs: Al crear un nuevo documento para "ADR Local", utilice el esquema de Frontmatter definido en los estándares de Evolith Core y ubíquelo en la carpeta de gobernanza correspondiente.