**Estado:**Production-ready · Adoptado activamente **Última revisión:**2026-05-30 **Responsable:**Equipo de arquitectura
Las shell libraries son paquetes NuGet internos compartidos a través de todos los bounded contexts de UMS. Se consumen como PackageReference desde github.com/beyondnetcode/Shell.* — nunca como project references locales.
| Librería | Paquetes NuGet | Propósito | Estado en UMS API |
|---|---|---|---|
BeyondNetCode.Shell.Ddd |
BeyondNetCode.Shell.Ddd · BeyondNetCode.Shell.Ddd.ValueObjects |
Tipos base DDD: Entity, AggregateRoot, ValueObject, DomainEvent, BrokenRules | Fundación core — cada aggregate la extiende |
BeyondNetCode.Shell.Factory |
BeyondNetCode.Shell.Factory · BeyondNetCode.Shell.DI |
Abstract factory basada en selector con DSL fluente | Activo — transitivo vía BeyondNetCode.Shell.Ddd; disponible para todas las capas |
BeyondNetCode.Shell.Aop |
BeyondNetCode.Shell.Aop · BeyondNetCode.Shell.DispatchProxy · BeyondNetCode.Shell.Aspects · BeyondNetCode.Shell.Logger.Serilog · BeyondNetCode.Shell.DI |
AOP basado en DispatchProxy: logging, retry, advice aspects | Activo — wireado a CreateTenantCommandHandler; expandir a otros handlers |
BeyondNetCode.Shell.Bootstrapper |
BeyondNetCode.Shell.Bootstrapper · BeyondNetCode.Shell.DI · BeyondNetCode.Shell.Observability |
Pipeline de inicialización composable (patrón Composite) | Disponible — usar para cadenas de startup multi-paso complejas |
github.com/beyondnetcode/Shell.Ddd/
├── BeyondNetCode.Shell.Ddd ← Entity, AggregateRoot, ValueObject, DomainEvent, DomainEnumeration
├── BeyondNetCode.Shell.Ddd.ValueObjects ← AuditValueObject, StringValueObject, IntValueObject, BoolValueObject, DecimalValueObject
github.com/beyondnetcode/Shell.Factory/
├── BeyondNetCode.Shell.Factory ← IFactory, AbstractFactorySetupSource, fluent DSL
├── BeyondNetCode.Shell.DI ← AddFactory() DI extension
github.com/beyondnetcode/Shell.Aop/
├── BeyondNetCode.Shell.Aop ← IAspect, IJoinPoint, IPointCut, OnMethodBoundaryAspect, OnRetryAspect
├── BeyondNetCode.Shell.DispatchProxy ← AopProxy<TService,TImpl>, AopProxyCreator
├── BeyondNetCode.Shell.Aspects ← LoggerAspect, AdviceAspect, RetryAspect + attributes
├── BeyondNetCode.Shell.Logger.Serilog ← SerilogLogger : ILogger (AOP)
├── BeyondNetCode.Shell.DI ← AddAop(), AddAopProxy<>()
github.com/beyondnetcode/Shell.Bootstrapper/
├── BeyondNetCode.Shell.Bootstrapper ← IBootstrapper, IBootstrapperAsync, CompositeBootstrapper
├── BeyondNetCode.Shell.DI ← DependencyInjectionBootstrapper
├── BeyondNetCode.Shell.Observability ← ObservabilityBootstrapper + ObservabilityConfigurationUms.Domain
└── BeyondNetCode.Shell.Ddd ← Entity, AggregateRoot
└── BeyondNetCode.Shell.Factory ← IFactory (transitivo)
└── BeyondNetCode.Shell.Ddd.ValueObjects ← AuditValueObject
Ums.Application
├── Ums.Domain (arriba)
└── BeyondNetCode.Shell.Aspects ← [LoggerAspect], [RetryAspect] contrato de atributos
Ums.Infrastructure
├── Ums.Application (arriba)
├── BeyondNetCode.Shell.DI ← AddAop(), AddAopProxy<>()
└── BeyondNetCode.Shell.Logger.Serilog ← SerilogLogger// 1. DDD: define tu aggregate
public class Order : AggregateRoot<Order, OrderProps> { ... }
// 2. Factory: despacha al handler correcto basado en estado runtime
For<Order, IFulfillmentStrategy>()
.Create<DigitalFulfillment>().When(o => o.Props.IsDigital);
// 3. AOP: agrega logging cross-cutting al command handler
[LoggerAspect(Type = typeof(IMelLogger), LogDuration = true)]
public async Task<Result<OrderId>> Handle(PlaceOrderCommand cmd, CancellationToken ct) { ... }
// 4. Bootstrapper: compos multi-step startup
new CompositeBootstrapper()
.Add(new DependencyInjectionBootstrapper(ConfigureServices))
.Add(new ObservabilityBootstrapper(services, obsConfig))
.Run();Un ejemplo completo end-to-end combinando las cuatro librerías está en**combined-usage.md**.
| Documento | Contenidos |
|---|---|
| ddd.md | Entity · AggregateRoot · ValueObject · DomainEvent · DomainEnumeration · BrokenRules · TrackingState |
| factory.md | AbstractFactorySetupSource · fluent DSL · IFactoryInterceptor · DI wiring · Patrones UMS |
| aop.md | Cadena IAspect · OnMethodBoundaryAspect · LoggerAspect · async proxy gap fix · MelLogger · DI wiring |
| bootstrapper.md | IBootstrapper · CompositeBootstrapper · DI/Observability bootstrappers |
| combined-usage.md | Ejemplo completo: Aggregate Fulfillment + factory routing + AOP logging + startup bootstrapped |
Cuando múltiples aspectos aplican al mismo método:
| Orden | Aspecto | Razón |
|---|---|---|
| 10 | Tracing | Debe capturar el span completo del request |
| 20 | Authorization | Rechazar temprano antes de cualquier trabajo real |
| 30 | Validation | Pre-condiciones de dominio |
| 40 | Idempotency | Verificar dedup store antes de ejecución |
| 50 | Logging (LoggerAspect) |
Observar la ejecución real |
| 60 | Metrics | Registrar duración/éxito después de logging |
| 70 | Transaction | Wrapper de retry más externo |
| Concern | Mecanismo | Archivo |
|---|---|---|
| PII en logs | MelLogger: log nombres/tipos de parámetros solo, nunca valores |
Ums.Infrastructure/Aop/MelLogger.cs |
| PII en Serilog | SensitiveDataResolver + atributo [Sensitive] |
BeyondNetCode.Shell.Logger.Serilog |
| Pureza de Domain | Ums.Domain.csproj tiene cero referencias NuGet de dominio |
AGENTS.md |
| Orden de Factory | FactorySetupProvider evalúa predicados en orden de declaración |
BeyondNetCode.Shell.Factory/Impl/FactorySetupProvider.cs |
| Aspectos async | OnMethodBoundaryAspect unwraps Task/Task<T> vía continuación |
BeyondNetCode.Shell.Aop/Impl/OnMethodBoundaryAspect.cs |
Ejecutar esto antes de cualquier PR que toque código que use las shell libraries:
# Desde src/
cd apps/ums.api
dotnet build Ums.sln
dotnet test Ums.sln --verbosity minimalEsperado: 0 errores de build, 0 fallos de testsen todas las suites.