2. Architecture
2.1 Layer Model
2.2 The Three-Line Wiring
The entire integration point between the ERP host and the E-Invoicing SDK is three lines, in
Shumoul.Infrastructure/Extensions/ServiceCollectionExtensions.cs:214-216:
services.AddEInvoicingSDK(config)
.UseAppSettings<AppSettingService>()
.IncludeApi();
AddEInvoicingSDK(config)— binds and validatesEGSConfigSettings/ZatcaPortalSettingsfromappsettings.json, registers localization, the SDK's own DI auto-registration, MediatR (scoped to the Framework's own assembly), and AutoMapper. Throws at startup if the required config sections are missing..UseAppSettings<AppSettingService>()— registers the ERP's ownAppSettingServiceclass as the concrete implementation of the SDK'sIEInvoicingAppSettingServiceabstraction. This is the only integration surface between the SDK and the ERP's own persistence/tenant model..IncludeApi()— loads the compiledShumoul.Framework.EInvoicing.Apiassembly as an ASP.NET Core MVC Application Part. This is how the SDK's controllers become live, routable endpoints in the same host process — no controller code is duplicated intoShumoul.Api, and no ERP-specific controller wraps or gates these endpoints.
2.3 Two-Layer Model — SDK + Thin API, Not SDK + ERP Integration Layer
Unlike the WhatsApp Integration Library (a stateless protocol client consumed by ERP-owned business services
that add tenant/business logic on top), E-Invoicing's "Api" layer is not an ERP integration layer — it's
a second, generic layer shipped by the same Framework package, exposing the SDK's own capabilities almost 1:1
as HTTP endpoints. There is no ERP-owned service comparable to TenantWhatsAppSender between Shumoul.Api's
business logic and the E-Invoicing SDK.
2.4 Dependency Direction — Clean From the SDK's Side
Shumoul.Framework.EInvoicing/.Tenancyeach reference only the Framework's own genericShumoul.Framework.Application/Shumoul.Framework.Infrastructurebase libraries — zero reference to ERP-internalShumoul.Application/Shumoul.Infrastructure/Shumoul.Domain.Shumoul.Framework.EInvoicing.ApireferencesShumoul.Framework.EInvoicing;Shumoul.Framework.EInvoicing.TenancyApireferencesShumoul.Framework.EInvoicing.Tenancy.Shumoul.BackEnd.slncontains zero direct project references to any EInvoicing project — the ERP consumes only the compiled NuGet package, consistent with the platform's Dependency Law.Shumoul.Framework.MultiTenancy.Api.csproj(inShumoul.MultiTenancyApi) referencesShumoul.Framework.EInvoicing.TenancyApithe same way.
2.5 The Tenancy Fork — Duplication, Not Adapter
Shumoul.Framework.EInvoicing.Tenancy is a byte-for-byte copy of the core SDK's namespace and class
structure — not a thin adapter reusing shared core logic with a different persistence backend. Every future
behavior change (a ZATCA rule update, a bug fix) must be made twice, in two places, to keep both variants
in sync. The fork's own DI bootstrap (AddEInvoicingTenancySDK) is entirely commented out — dead code.
2.6 What's Missing Compared to the Platform's Certified Frameworks
| Characteristic | Notification / Background Jobs / WhatsApp | E-Invoicing |
|---|---|---|
| Standalone repository | Yes, all three | No — lives inside Shumoul.Framework |
| ERP-owned business integration layer | Yes (e.g. WhatsAppOtpMessageService) | No — SDK's own generic controllers are the only entry point |
| Wired into a real ERP workflow | Yes | Not found — no Sales/Purchase invoice service calls it |
| Background/retry integration | Yes (Notification Framework retry pipeline) | None |
| ADR documenting the boundary decision | Yes (WhatsApp's ADR-001) | None found |
| Golden Reference certification | Notification + Background Jobs are certified | Not applicable yet |
2.7 Boundary Verdict
E-Invoicing sits in a hybrid state: too generic and too directly exposed to be safely called "ERP code," but missing the Host Adapter layer, the ADR, the retry/notification integration, and the tenant-aware security posture that would let it stand as a peer to the platform's certified Frameworks. It has the packaging shape of a Framework (versioned NuGet packages, dependency-clean from ERP internals, its own test project) but not the integration shape every certified Framework has.
