3. Packages
Repo: Shumoul.Saas.BackgroundJobsFramework. All 5 published packages ship at version 1.0.0, targeting
net9.0 only. A 6th, unpublished test project (Shumoul.BackgroundJobs.Tests, IsPackable=false) completes
the repo.
3.1 Shumoul.BackgroundJobs.Contracts
Purpose: the generic runtime vocabulary — job identity, status, trigger type, priority, retry policy, tenant info, lock key, schedule request, execution result, failure category.
Responsibilities: enums and records/DTOs only. No logic beyond simple computed properties and static factory methods.
Depends on: nothing — zero ProjectReference/PackageReference beyond the SDK itself. A true leaf.
Forbidden dependencies: everything — this package must never gain a dependency on anything.
3.2 Shumoul.BackgroundJobs.Abstractions
Purpose: interfaces only — the runtime contracts (IBackgroundJob, executor, pipeline, execution
context, scheduler, tenant context, distributed lock, failure classifier) plus the adapter contracts
(Hangfire, tenant resolver, distributed lock, logging, notification).
Depends on: Contracts only.
Forbidden dependencies: any infrastructure package, any ERP assembly, Core, Adapters.
3.3 Shumoul.BackgroundJobs.Core
Purpose: the runtime engine itself — pipeline orchestration, execution wrapping, scheduling delegation,
tenant scoping, distributed-lock delegation, failure classification. Owns the Core-level DI entry point
AddBackgroundJobsFrameworkCore.
Depends on: Abstractions; Microsoft.Extensions.DependencyInjection.Abstractions 9.0.0;
Microsoft.Extensions.Configuration.Abstractions 9.0.0 (present for future use — nothing in current Core
source actually consumes configuration types yet).
Forbidden dependencies: Adapters (a sibling, never a chained dependency), Hangfire, EF Core,
MultiTenancy, any ERP assembly — confirmed zero such references anywhere in Core.
3.4 Shumoul.BackgroundJobs.Adapters
Purpose: the framework's own infrastructure adapters — the only place in the framework where Hangfire and MultiTenancy types are referenced. This is the framework side of the two-tier adapter model — see §7 — Adapters.
Depends on: Abstractions; Hangfire.Core 1.8.21; Shumoul.Framework.MultiTenancy 1.0.77.
Forbidden dependencies: Core (a sibling, never a chained dependency), any ERP assembly, any
Shumoul.Notification.* package.
3.5 Shumoul.BackgroundJobs (Entry Point)
Purpose: the module's single entry point — one-line DI wiring,
AddShumoulBackgroundJobsFramework() => services.AddBackgroundJobsFrameworkCore(). Exposes no controllers —
the Hangfire Dashboard's mounting, route, and authorization stay permanently host-owned (ADR-004).
Depends on: Core; Microsoft.Extensions.DependencyInjection.Abstractions 9.0.0.
Forbidden dependencies: Adapters — the host wires both packages independently, side by side, never
through the entry package.
3.6 Shumoul.BackgroundJobs.Tests (unpublished)
Purpose: unit, DI/host-graph, adapter, and end-to-end tests for the framework itself.
Depends on: all 4 published packages via direct project reference (including Abstractions and
Adapters directly, not merely the entry package); Microsoft.Extensions.DependencyInjection 9.0.9 (the
full DI container, for BuildServiceProvider graph tests); xunit 2.9.2; Microsoft.NET.Test.Sdk 17.12.0.
Forbidden dependencies: any ERP assembly, any Notification Framework package.
3.7 Dependency graph
Confirmed against the actual .csproj files, not assumed from documentation: Core and Adapters are
siblings — neither references the other, both depend only on Abstractions. The ERP host
(Shumoul.Infrastructure.csproj) references exactly two packages directly:
<PackageReference Include="Shumoul.BackgroundJobs" Version="1.0.0" />
<PackageReference Include="Shumoul.BackgroundJobs.Adapters" Version="1.0.0" />
Core, Abstractions, and Contracts are pulled in transitively — the host never references them
directly. There is zero ProjectReference from the ERP to any framework project, matching the
platform's Dependency Law ("PackageReference only, across every module boundary").
3.8 Package graph — publication and distribution
| Package | Published to |
|---|---|
Shumoul.BackgroundJobs.Contracts | C:\MultiTenancy\ (developer staging) + local-packages\ (CI restore source) in the framework repo, then copied into the ERP repo's own local-packages\ |
Shumoul.BackgroundJobs.Abstractions | same |
Shumoul.BackgroundJobs.Core | same |
Shumoul.BackgroundJobs.Adapters | same |
Shumoul.BackgroundJobs (entry) | same |
The ERP's nuget.config defines a LocalShumoul feed pointing at its own local-packages\ folder — this is
the actual restore source any consumer build uses; C:\MultiTenancy\ is only the developer's local staging
copy and is not consulted directly by CI or consumer builds. All 5 .nupkg files are confirmed present in
the ERP's local-packages\ at version 1.0.0.
3.9 Ownership summary
| Owner | Owns | Must NOT own |
|---|---|---|
Contracts | Enums, records, DTOs — pure data shapes | Any logic, any dependency |
Abstractions | Every interface (runtime + adapter contracts) | Any concrete implementation |
Core | The runtime engine's concrete implementations | Hangfire, MultiTenancy, EF Core, any ERP type |
Adapters | Framework-owned infrastructure adapters (Hangfire, MultiTenancy) | Business logic, any ERP type, Core |
| Entry point | DI wiring only | Controllers, Hangfire Dashboard mounting |
| ERP Host | Job-specific adapters, Hangfire-callable bridges, recurring-job registration/cutover, DI composition order, Dashboard authorization, job-tracking persistence | Generic/reusable runtime logic that has no ERP dependency |