Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DECISIONS.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ _Nota: Las decisiones universales se heredan del Upstream Base ([evolith_arch32]

| 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 para projects discretos |
| T-001 | Orquestación de Monorepo con Nx | Adoptar | ADR-0001 | [T-001](./docs/adrs/T-001-nx-monorepo-orchestration.es.md) | **Corregido 2026-08-01 (`GAP-015`):** la entrada anterior decía «npm workspaces con Nx», y ningún `package.json` del repositorio declara `workspaces` — nunca se usaron. Nx orquesta por GRAFO DE PROYECTOS: `project.json` más los plugins de inferencia `@nx/vite`, `@nx/webpack`, `@nx/eslint` y `@nx/jest` declarados en `src/nx.json`. La razón que decidió es que el repositorio no es homogéneo: `tracker-api` es .NET, y npm workspaces enlaza `node_modules` entre paquetes npm — habría cubierto tres proyectos de cuatro dejando fuera al mayor. |
| T-002 | Adopción de Microfrontends en Fase 1| Sobrescribir | N/A | [T-002](docs/adrs/T-002-microfrontends.md) | Desviación de la topología base de Fase 1 para permitir escalabilidad concurrente de UI |
| T-003 | Arquitectura Hexagonal (Ports & Adapters) | Adoptar | ADR-0002 (Core Node.js) | — | Capa de dominio sin imports de NestJS, ORM ni SDKs externos |
| T-004 | TypeScript estricto como lenguaje primario | Adoptar | ADR-0003 | — | `strict: true` habilitado; imports sin usar prohibidos |
Expand Down
2 changes: 1 addition & 1 deletion DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ _Nota: Las decisiones universales se heredan del Upstream Base ([evolith_arch32]

| 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-001 | Orquestación de Monorepo con Nx | Adoptar | ADR-0001 | [T-001](./docs/adrs/T-001-nx-monorepo-orchestration.md) | **Corregido 2026-08-01 (`GAP-015`):** la entrada anterior decía «npm workspaces con Nx», y ningún `package.json` del repositorio declara `workspaces` — nunca se usaron. Nx orquesta por GRAFO DE PROYECTOS: `project.json` más los plugins de inferencia `@nx/vite`, `@nx/webpack`, `@nx/eslint` y `@nx/jest` declarados en `src/nx.json`. La razón que decidió es que el repositorio no es homogéneo: `tracker-api` es .NET, y npm workspaces enlaza `node_modules` entre paquetes npm — habría cubierto tres proyectos de cuatro dejando fuera al mayor. |
| T-002 | Adopción de Microfrontends en Fase 1 | Sobrescribir | N/A | [T-002](./docs/adrs/T-002-microfrontends-fase1.md) | 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. |
Expand Down
100 changes: 100 additions & 0 deletions docs/adrs/T-001-nx-monorepo-orchestration.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
adr: T-001
title: Nx orquesta el monorepo, y lo hace por grafo de proyectos — no con npm workspaces
status: Accepted
date: 2026-08-01
tags: [EvolithSatellite, monorepo, build, tooling, nx]
authority: Retro-documenta la decisión registrada como T-001 en DECISIONS.md desde el primer commit del repositorio
relates: [T-006 frontend Vite, T-002 microfrontends fase 1, T-043 Helm supersede a Kustomize]
gaps: [GAP-015]
---

# ADR T-001 — Nx orquesta el monorepo

## Status

Aceptado, **escrito el 2026-08-01** para cerrar `GAP-015`. La decisión en sí es la más antigua del
repositorio: `DECISIONS.md` lleva `T-001` desde el principio. Lo que nunca llevó fue el *porqué* —
su entrada entera decía *«Inicializado en `src/` utilizando npm workspaces con Nx»*, que enuncia un
resultado y, según resulta, lo enuncia mal.

## Context

`GAP-015` dice que a `DECISIONS.md` le falta el racional técnico de T-001. Verificarlo produjo un
segundo hallazgo que la fila no menciona: **la única línea que sí tiene es inexacta.**

Medido contra el repositorio el 2026-08-01:

- **Ningún `package.json` de este repositorio declara un campo `workspaces`.** Ni
`src/package.json` ni ningún otro. npm workspaces no se usa, ni se usó nunca.
- Nx descubre proyectos mediante **ficheros `project.json` y plugins de inferencia** —
`@nx/vite/plugin`, `@nx/webpack/plugin`, `@nx/eslint/plugin` y `@nx/jest/plugin` están declarados
en `src/nx.json`, e infieren los targets de la configuración propia de cada proyecto en vez de
una lista de paquetes.
- El workspace tiene cuatro proyectos bajo `src/apps/`: `tracker-api`, `tracker-gateway`,
`tracker-web` y `tracker-web-e2e`.

Que eso importe es justamente el motivo de escribirlo. Quien leyera la entrada antigua buscaría un
array `workspaces`, no lo encontraría, y concluiría razonablemente que el monorepo está mal
configurado — cuando lo cierto es que está configurado de otra manera.

## Decision

**Nx es el orquestador de este monorepo, a través de su grafo de proyectos. npm workspaces no se
usa, y eso es deliberado y no un olvido.**

Tres razones, en el orden que decidió:

### 1. El repositorio no es homogéneo, y npm workspaces da por hecho que sí

`tracker-api` es **.NET**. npm workspaces enlaza `node_modules` entre paquetes npm; no tiene
opinión sobre un `.csproj`, no puede ordenar un `dotnet build` frente a un `vite build`, y no puede
expresar que los tests de contrato del gateway dependen del schema de la API. Adoptarlo habría
cubierto tres proyectos de cuatro y dejado fuera al mayor, precisamente de la herramienta que debe
describir el conjunto.

El grafo de Nx es agnóstico del lenguaje: un proyecto es lo que se declare como tal, y una
dependencia es lo que se declare.

### 2. Inferencia antes que declaración, porque una lista de targets escrita a mano deriva

Los plugins derivan los targets de cada proyecto de la configuración que ese proyecto ya tiene —su
config de Vite, de ESLint, de Jest—. La alternativa es una segunda copia de esa información dentro
de un manifiesto de workspace, y una segunda copia es algo que olvidar. Este repositorio ha gastado
tiempo real exactamente en ese modo de fallo: listas de paquetes de Docker escritas a mano
(`GT-647`), un snapshot de evaluabilidad mantenido a mano (`GT-640`), un contrato transcrito a mano
(`ADR T-038`). Aquí aplica el mismo razonamiento.

### 3. La ejecución por afectación necesita un grafo de verdad

`nx affected` vale lo que valgan las aristas de dependencia que es capaz de ver. npm workspaces
expresa «el paquete A depende del B» y nada sobre un `.csproj` que referencia a otro, o un proyecto
e2e que depende de la app que conduce. Sin esas aristas, «ejecuta lo que cambió» degenera en
«ejecuta todo», y con ello se va el valor que justificaba el monorepo.

## Consequences

- **Quien contribuya no debe buscar `workspaces` en `package.json`.** Está ausente a propósito. El
grafo lo definen `src/nx.json` y el `project.json` de cada proyecto.
- **Añadir un proyecto es darle un `project.json`** (o una configuración que un plugin de
inferencia reconozca), no añadir una ruta a un array.
- **El coste es una dependencia de herramienta.** Nx está pineado en `^22.7.5`; sus plugins son lo
que sabe construir cada proyecto, así que una subida mayor es un evento de todo el repositorio y
no de un paquete. Ese es el intercambio aceptado a cambio de un solo grafo sobre cuatro proyectos
heterogéneos.
- **npm workspaces sigue disponible** si el repositorio llegara a ser solo npm, cosa que no ocurrirá
mientras la API sea .NET. Cambiarlo pasa por revisar este ADR, no por añadir el campo.

## Validation

- `grep -L workspaces $(find . -name package.json -not -path '*/node_modules/*')` devuelve todos los
ficheros — ninguno lo declara.
- `src/nx.json` lista los cuatro plugins de inferencia nombrados arriba.
- `src/apps/tracker-web/project.json` existe; `src/apps/tracker-api` no tiene ninguno, porque su
build lo conduce `dotnet` y sus targets no los infiere un plugin de npm — el caso concreto que
describen las razones 1 y 3.

## References

- `DECISIONS.md` → `T-001`, cuya entrada de una línea este ADR corrige y amplía.
- `GAP-015` — la fila que pidió este racional.
98 changes: 98 additions & 0 deletions docs/adrs/T-001-nx-monorepo-orchestration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
adr: T-001
title: Nx orchestrates the monorepo, and it does so through project graphs — not npm workspaces
status: Accepted
date: 2026-08-01
tags: [EvolithSatellite, monorepo, build, tooling, nx]
authority: Retro-documents the decision recorded as T-001 in DECISIONS.md since the repository's first commit
relates: [T-006 frontend Vite, T-002 microfrontends phase 1, T-043 Helm supersedes Kustomize]
gaps: [GAP-015]
---

# ADR T-001 — Nx orchestrates the monorepo

## Status

Accepted, **written 2026-08-01** to close `GAP-015`. The decision itself is the repository's
oldest: `DECISIONS.md` has carried `T-001` since the beginning. What it never carried was the
*why* — its whole entry read *"Inicializado en `src/` utilizando npm workspaces con Nx"*, which
states an outcome and, as it turns out, states it wrongly.

## Context

`GAP-015` says `DECISIONS.md` lacks T-001's technical rationale. Verifying it produced a second
finding the row does not mention: **the one line the entry does have is inaccurate.**

Measured against the repository on 2026-08-01:

- **No `package.json` in this repository declares a `workspaces` field.** Not `src/package.json`,
not any other. npm workspaces is not in use and never was.
- Nx discovers projects through **`project.json` files and inference plugins** — `@nx/vite/plugin`,
`@nx/webpack/plugin`, `@nx/eslint/plugin` and `@nx/jest/plugin` are declared in `src/nx.json`,
and they infer targets from each project's own configuration rather than from a package list.
- The workspace holds four projects under `src/apps/`: `tracker-api`, `tracker-gateway`,
`tracker-web` and `tracker-web-e2e`.

That mattering is the point of writing this down. Someone reading the old entry would look for a
`workspaces` array, not find one, and reasonably conclude the monorepo was misconfigured — when
what is actually true is that it was configured a different way.

## Decision

**Nx is the orchestrator of this monorepo, through its project graph. npm workspaces is not used,
and this is deliberate rather than an omission.**

Three reasons, in the order that decided it:

### 1. The repository is not homogeneous, and npm workspaces assumes it is

`tracker-api` is **.NET**. npm workspaces links `node_modules` between npm packages; it has no
opinion about a `.csproj`, cannot order a `dotnet build` against a `vite build`, and cannot express
that the gateway's contract tests depend on the API's schema. Adopting it would have covered three
projects of four and left the largest one outside the tool that is supposed to describe the whole.

Nx's graph is language-agnostic: a project is whatever declares itself one, and a dependency is
whatever is declared.

### 2. Inference over declaration, because a hand-maintained target list drifts

The plugins derive each project's targets from the configuration that project already has — its
Vite config, its ESLint config, its Jest config. The alternative is a second copy of that
information inside a workspace manifest, and a second copy is a thing to forget. This repository
has spent real time on exactly that failure mode elsewhere: hand-written Docker package lists
(`GT-647`), a hand-maintained evaluability snapshot (`GT-640`), a hand-transcribed contract
(`ADR T-038`). The same reasoning applies here.

### 3. Affected-based execution needs a real graph

`nx affected` is only as good as the dependency edges it can see. npm workspaces expresses
"package A depends on package B" and nothing about a `.csproj` referencing another, or an e2e
project depending on the app it drives. Without those edges, "run what changed" degrades to "run
everything", and the value that justified a monorepo goes with it.

## Consequences

- **Contributors must not look for `workspaces` in `package.json`.** It is absent on purpose. The
project graph is defined by `src/nx.json` plus each project's `project.json`.
- **Adding a project means giving it a `project.json`** (or a configuration an inference plugin
recognises), not adding a path to a workspace array.
- **The cost is a tool dependency.** Nx is pinned at `^22.7.5`; its plugins are the thing that
knows how to build each project, so a major upgrade is a repository-wide event rather than a
package-local one. That is the trade accepted in exchange for one graph over four heterogeneous
projects.
- **npm workspaces remains available** if the repository ever becomes npm-only, which it will not
while the API is .NET. Revisiting this ADR is the way to change that, not adding the field.

## Validation

- `grep -L workspaces $(find . -name package.json -not -path '*/node_modules/*')` returns every
file — none declares one.
- `src/nx.json` lists the four inference plugins named above.
- `src/apps/tracker-web/project.json` exists; `src/apps/tracker-api` has none, because its build is
driven by `dotnet` and its targets are not inferred by an npm plugin — the concrete case that
rules 1 and 3 describe.

## References

- `DECISIONS.md` → `T-001`, whose one-line entry this ADR corrects and expands.
- `GAP-015` — the row that asked for this rationale.
Loading
Loading