using System.Reflection; using GB5Shared.GOP.Qualifier; using GB5Shared.Auth.Jwt; using GB5Shared.Authorization; using GB5Shared.DaprCache; using GB5Shared.EntityHandler; using GB5Shared.GB5Library.Qualifier; using GB5Shared.Hosting; using GB5Shared.ListQuery; using GB5Shared.PubSub.OutBox; using GB5Shared.Storage; using GB5Shared.Vault; using GB5Shared.WorkFlow.WorkFlowEngine; namespace DXPSL; // Host-aggregation entry point (GB5Shared.Hosting.IModule) — for folding DXP into PlatformHost // later. Per IDMS's own precedent (IDMSModule.cs), do NOT wire this into PlatformHost.csproj // until AddFastEndpoints DI validation passes with DXPSL running standalone first — IDMS hit a // missing IListHandler at host-aggregation time and had to stay standalone. DXPSL's own // Program.cs is therefore the source of truth for local dev/testing until that's verified. public class DXPModule : IModule { public void Register(IServiceCollection services, IConfiguration configuration) { services.AddScoped(); // VerifyKyc.cs is gated via [MenuRights] instead of the vendor JWT scheme (a GB-client-side // internal-admin action, not vendor self-service) — mirrors Entitlement's identical // registration (Thread 0 §20.1), added here too for host-aggregated-mode parity. services.AddMenuRightsAuthorization(); // Universal Save Execution Pipeline — same set as DXPSL/Program.cs (standalone path), // duplicated here so host-aggregated mode gets an identical DI graph (matches // PERMModule.cs/PERMSL Program.cs's dual-registration pattern). services.AddScoped(); services.AddScoped(typeof(BaseEntityAppService<>), typeof(BaseEntityAppService<>)); services.AddScoped(); services.AddGB5QualifierEngine(); services.AddScoped(); // Universal Attachment System — KYC document upload (Phase 1.2), same as Program.cs. services.AddGB5Storage(configuration.GetSection("StorageConfiguration")); services.Configure(configuration.GetSection(GB5Shared.Attachment.AttachmentPathSettings.Section)); // IAttachmentUploadService/ITemplateResolutionEngine/IAttachmentPathResolutionService/ // IAttachmentResolveDAL now live in GB5Shared.Attachment — not covered by the // DXPBLL/DXPDAL scan below (KycBLL/AsnBLL take IAttachmentResolveDAL directly). services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // DXPJwtService needs IJwtAccessTokenIssuer (vendor context-switch JWTs) — same as // DXPSL/Program.cs's standalone path and EntitlementModule.cs's identical // host-aggregation precedent. services.AddGB5Vault(configuration); services.AddGB5JwtIssuer(); var bll = Assembly.Load("DXPBLL"); var dal = Assembly.Load("DXPDAL"); services.Scan(scan => scan .FromAssemblies(bll, dal) .AddClasses(c => c.Where(t => !t.IsAbstract && !t.IsInterface && !typeof(Microsoft.Extensions.Hosting.IHostedService).IsAssignableFrom(t))) .AsImplementedInterfaces() .WithScopedLifetime()); // List-query infrastructure + MM cross-service HTTP client (Phase 1.3), same as // Program.cs. services.AddListInfrastructure(dal); services.AddHttpClient("MMModule", c => { c.BaseAddress = new Uri(configuration["Integration:MMModuleBaseUrl"] ?? throw new InvalidOperationException("Integration:MMModuleBaseUrl not configured")); c.Timeout = TimeSpan.FromSeconds(15); }); // DXPHub — real-time PO/ASN/Invoice status push (Phase 1.6), same as Program.cs. // NOTE: host-aggregated mode still needs the JWT bearer OnMessageReceived hook Program.cs // configures (so the WebSocket transport can carry ?access_token=) — PlatformHost's own // JWT registration must add that same event before this module is actually wired in. services.AddSignalR(options => { options.EnableDetailedErrors = false; options.MaximumReceiveMessageSize = 32 * 1024; options.ClientTimeoutInterval = TimeSpan.FromSeconds(60); options.KeepAliveInterval = TimeSpan.FromSeconds(15); }); services.AddSingleton(); } public void MapEndpoints(WebApplication app) { app.MapHub("/hubs/dxp"); } }