Estado: Aceptado
Fecha: 2026-05-15
Enmendado: 2026-05-24 — grafo de dependencias corregido; alcance extendido para incluir BeyondNetCode.Shell.Aop y BeyondNetCode.Shell.Bootstrapper
Responsable de Decisión: Arquitectura
Relacionados:
UMS incluye librerías de infraestructura reutilizables bajo src/libs/shell. Estas librerías se originaron de fuentes externas o de referencia, pero UMS no debe exponer namespaces upstream ni convenciones de repositorio en código de aplicación.
El ADR-0029 anterior describía “Primitivas DDD nativas de C# (sin librería externa)”. Esa redacción ya no es precisa: la posición correcta es que UMS posee su superficie de dependencia de dominio a través de las shell libraries BeyondNetCode.Shell.*. Las capas de aplicación consumen la abstracción shell de UMS, no la identidad fuente upstream.
A partir de 2026-05-24, la capa shell incluye cuatro grupos de librerías:
| Grupo | Proyectos | Capas consumidoras |
|---|---|---|
BeyondNetCode.Shell.Ddd |
BeyondNetCode.Shell.Ddd · BeyondNetCode.Shell.Ddd.ValueObjects |
Domain (directo) |
BeyondNetCode.Shell.Factory |
BeyondNetCode.Shell.Factory · BeyondNetCode.Shell.DI |
Domain (transitivo vía Ddd) · Infrastructure (directo) |
BeyondNetCode.Shell.Aop |
BeyondNetCode.Shell.Aop · BeyondNetCode.Shell.DispatchProxy · BeyondNetCode.Shell.Aspects · BeyondNetCode.Shell.Logger.Serilog · BeyondNetCode.Shell.DI |
Application (contrato de atributos) · Infrastructure (wiring DI + adapters) |
BeyondNetCode.Shell.Bootstrapper |
BeyondNetCode.Shell.Bootstrapper · BeyondNetCode.Shell.DI · BeyondNetCode.Shell.AutoMapper · BeyondNetCode.Shell.Observability |
Infrastructure · Presentation (startup) |
UMS adopta una estrategia de Aislamiento de Shell Libraries para todos los patrones compartidos de infraestructura:
BeyondNetCode.Shell.*.BeyondNet.* o nombres de repositorio fuente como csdevlib.*.net10.0).Ums.Presentation
├── Ums.Application
└── Ums.Infrastructure
Ums.Infrastructure
├── Ums.Application
├── Ums.Domain
├── BeyondNetCode.Shell.DI
│ └── BeyondNetCode.Shell.Aspects (transitivo)
│ └── BeyondNetCode.Shell.Aop (transitivo)
│ └── BeyondNetCode.Shell.DispatchProxy (transitivo)
└── BeyondNetCode.Shell.Logger.Serilog (transitivo vía installer)
Ums.Application
├── Ums.Domain
└── BeyondNetCode.Shell.Aspects ← contrato de atributos solo (sin DI, sin proxy runtime)
Ums.Domain
├── BeyondNetCode.Shell.Ddd
│ └── BeyondNetCode.Shell.Factory (transitivo vía Ddd)
└── BeyondNetCode.Shell.Ddd.ValueObjects
└── BeyondNetCode.Shell.Ddd (transitivo)
Corrección del ADR original (2026-05-15):
Ums.Domain.csprojpreviamente listaba una<ProjectReference>directa aBeyondNetCode.Shell.Factory. Esto era una referencia redundante —BeyondNetCode.Shell.Dddya depende deBeyondNetCode.Shell.Factory, haciéndola disponible transitivamente. La referencia directa fue removida el 2026-05-24. El código de Domain debe acceder a abstracciones de factory solo a través de la capa shell DDD, no importando directamente el namespace de Factory.
| Capa | Puede referenciar | NO puede referenciar |
|---|---|---|
Ums.Domain |
BeyondNetCode.Shell.Ddd, BeyondNetCode.Shell.Ddd.ValueObjects |
Cualquier BeyondNetCode.Shell.Aop.*, BeyondNetCode.Shell.Factory (directo), BeyondNetCode.Shell.Bootstrapper.* |
Ums.Application |
Ums.Domain, BeyondNetCode.Shell.Aspects (contrato de atributos) |
BeyondNetCode.Shell.DispatchProxy, BeyondNetCode.Shell.Aop.*.Installer, BeyondNetCode.Shell.Factory, BeyondNetCode.Shell.Bootstrapper.* |
Ums.Infrastructure |
Todo lo anterior + AOP installer + Bootstrapper | — |
Ums.Presentation |
Todas las capas + Bootstrapper para startup | — |
Ums.Application referencia solo el contrato de atributo de AOP (BeyondNetCode.Shell.Aspects) — los handlers declaran intención cross-cutting vía atributos sin acoplamiento a la infraestructura de proxy.src/libs/shell sin tocar las capas de aplicación.IMelLogger (interfaz marker en Application, adapter concreto en Infrastructure) demuestra cómo aplicar el mismo principio de aislamiento a adapters cross-cutting.OpenTelemetry.Api en Bootstrapper) afectan la salud del build de UMS.BeyondNetCode.Shell.Ddd depende de BeyondNetCode.Shell.Factory — este acoplamiento es intencional (la construcción DDD puede usar abstracciones de factory internamente) pero significa que agregar una dependencia de Factory a Domain es suficiente para arrastrar Factory a todas partes donde Domain es referenciado.Las siguientes verificaciones son obligatorias después de cualquier cambio en las referencias de shell libraries:
# 1. Build de la solución completa
dotnet build src/apps/ums.api/Ums.sln
# 2. Ejecutar todos los test suites de shell libraries
dotnet test src/libs/shell/aop/src/BeyondNetCode.Shell.Aop.Tests/BeyondNetCode.Shell.Aop.Tests.csproj --verbosity minimal
dotnet test src/libs/shell/factory/src/BeyondNetCode.Shell.Factory.Test/BeyondNetCode.Shell.Factory.Test.csproj --verbosity minimal
# 3. Verificar pureza del Domain (sin refs AOP en Domain)
grep -r "BeyondNetCode.Shell.Aop" src/apps/ums.api/Ums.Domain/ --include="*.csproj"
# Esperado: sin output
# 4. Verificar que no hay ref directa a Factory en Domain (debe ser solo transitiva)
grep "BeyondNetCode.Shell.Factory" src/apps/ums.api/Ums.Domain/Ums.Domain.csproj
# Esperado: sin output
Este ADR clarifica ADR-0029. El estándar de implementación es:
El código de dominio de UMS no debe depender directamente de librerías de patrones externas no gestionadas. Puede depender de shell libraries poseídas por UMS que encapsulan y normalizan esos patrones. Cada shell library tiene un contrato de capa consumidora definido; ver la tabla arriba.
| Índice ADR | Overview de Shell Libraries | ADR-0060 Estrategia AOP |