Skip to content

SAIF.NetCore.ServiceExtensions dependencies

SAIF.NetCore.ServiceExtensions directly references ten other same-repo SAIF packages as dependency-injection composition-root wiring, carries eight direct third-party packages (three ASP.NET Core/DI packages plus five OpenTelemetry packages), and makes no outbound HTTP call of its own code against an external service — but it does reach EnvironmentClient's remote Environment API through calls it makes directly into EnvironmentClient's own registered implementation (see the EnvironmentClient row and API dependencies below), so "resolves/registers types" is not true of every internal reference.

Internal dependencies

Dependency Reference Type Usage
SAIF.NetCore.ServiceContracts NuGet Package (same-repo) Foundation interfaces/POCOs/exceptions used throughout the composition surface (IErrorHandleable, SAIFException, SystemType, ShutdownExemptExceptionType, and others).
SAIF.NetCore.AuthService NuGet Package (same-repo) RegisterEdgeAPIAuthServices/RegisterCoreAPIAuthServices register AuthService's JWT/dual-authentication, identity, and SecurityApi authorization types (ConfigureJwtBearerOptions, AddTokenIdentityService, AddIdentityAccessor, AddDualAuthentication, AddSecurityApiAuthorizeAttribute) — DI composition-root wiring, not an outbound call made by this library.
SAIF.NetCore.DBConnectionClient NuGet Package (same-repo) RegisterDBConnectionClient constructs and registers ConnectionClient/IDBConnectionClient — composition-root wiring; ConnectionClient's own outbound HTTP calls happen later, through the already-registered IHttpJsonClient, not during registration.
SAIF.NetCore.EnvironmentClient NuGet Package (same-repo) RegisterEnvironmentClient/RegisterSecureEnvironmentClient register BaseEnvironmentClient/SecureEnvironmentClient as IEnvironmentClient (DI composition-root wiring). This library also reaches that registered IEnvironmentClient at runtime, not just at registration time: the RegisterDBConnectionClient factory calls IEnvironmentClient.GetSecureSetting(key) the first time IDBConnectionClient is resolved, and AspNetSessionIdMiddleware calls IEnvironmentClient.GetSettingValueAsync(key) on every request where the session cookie is absent. Both calls can reach EnvironmentClient's remote Environment API over HTTP on a cache miss — this is a real, reachable remote dependency, not local-provider-only configuration reads.
SAIF.NetCore.ErrorHandler NuGet Package (same-repo) RegisterErrorHandlerService (also called by RegisterFactoryActivatedMiddleware) registers ErrorHandler as a scoped IErrorHandleable, consumed by this library's own DynamicErrorHandler middleware; RegisterForWindowsService<T> separately registers WindowsServiceErrorHandler as a singleton IWindowsServiceErrorHandler and SaifWindowsServiceLog as a singleton ISaifWindowsServiceLogService — distinct registrations, not both performed by the same method.
SAIF.NetCore.HttpClients NuGet Package (same-repo) Registers HttpJsonClient as IHttpJsonClient (ServiceContracts) for use by composed services such as ConnectionClient.
SAIF.NetCore.Logging NuGet Package (same-repo) RegisterLoggingService registers SaifLog as a singleton ISaifLogService; ConfigureSaifLogger separately calls .Configure(apiUrl, applicationData) on the already-registered ISaifLogService instance (it registers nothing itself). RegisterForWindowsService<T> registers SaifWindowsServiceLog as ISaifWindowsServiceLogService instead, and IHostBuilderExtensions's console-host builders register ConsoleLogService as IConsoleLogService — each logger variant is wired by a different method for a different host shape, not interchangeably by RegisterLoggingService/ConfigureSaifLogger alone.
SAIF.NetCore.OIDC NuGet Package (same-repo) RegisterOidcServices/AddWebAuthentication register OIDC's own middleware and services (JwtClaimMiddleware, RefreshJwtMiddleware, OidcSettings, RoleClaimTransformer, LoginRedirectService, cookie/OIDC options configurators) — composition-root wiring; the actual OIDC/token-exchange network calls happen inside OIDC's own implementation against the external Okta provider.
SAIF.NetCore.PingableService NuGet Package (same-repo) WithPingableController() registers the health/ping endpoint contributed by this package.
SAIF.NetCore.SystemHash NuGet Package (same-repo) RegisterSecureEnvironmentClient adds a singleton IEnvironmentClient descriptor (type-based, SecureEnvironmentClient) and a separate singleton ISystemHashService factory, () => new SystemHashService(Assembly.GetAssembly(type)) — this only selects and stores the caller-supplied assembly for later Get calls; constructing SystemHashService performs no hash computation, so no credential/hash is computed or cached at registration time. Each subsequent resolution-time call to Get(SystemType) computes and salts a hash freshly (see Compute salted system hash). This is distinct from RegisterDBConnectionClient, whose own IDBConnectionClient factory explicitly constructs a separate, unregistered SystemHashService and calls Get(SystemType.WebApp) on it directly — a hash computation that does happen, once, the first time the DB connection client singleton is resolved (see Register DB connection client step 3). This library's direct reference to SystemHash also makes HashUtil transitively available to consumers, since SystemHash itself directly references HashUtil (see Dependency risks and notes below).

External dependencies

Dependency Version Usage
Microsoft.AspNetCore.Authentication.Negotiate 8.0.0 (net8.0) / 10.0.12 (net10.0) Supplies the IIS/Negotiate Windows authentication scheme used by AppStartup and AddDualAuthentication-based Core/internal hosts.
Microsoft.AspNetCore.Mvc.NewtonsoftJson 8.0.0 (net8.0) / 10.0.12 (net10.0) .AddNewtonsoftJson() is called from AppStartup, OidcRazorStartup, and BaseApiStartup.ConfigureMvcBuilder when EnableNewtonsoftJsonSerializer is set, enabling the optional Newtonsoft JSON serializer for MVC.
Microsoft.Extensions.DependencyInjection 8.0.0 (both net8.0 and net10.0) Supplies the IServiceCollection extension-method surface underlying all registration code in this library; not bumped to a 10.x version on the net10.0 target framework*.
OpenTelemetry.Exporter.OpenTelemetryProtocol 1.9.0 UseOtlpExporter() in OpenTelemetryExtensions.ConfigureOpenTelemetry configures the OTLP exporter.
OpenTelemetry.Extensions.Hosting 1.9.0 AddOpenTelemetry() host integration entry point used by ConfigureOpenTelemetry.
OpenTelemetry.Instrumentation.AspNetCore 1.9.0 AddAspNetCoreInstrumentation() for ASP.NET Core request metrics and tracing.
OpenTelemetry.Instrumentation.Http 1.9.0 AddHttpClientInstrumentation() for outbound HttpClient metrics and tracing.
OpenTelemetry.Instrumentation.Runtime 1.9.0 AddRuntimeInstrumentation() for .NET runtime metrics.

Transitive dependencies

Dependencies in this section are inherited from dependency framework libraries. They are not directly referenced by this library but are required at runtime through framework packages.

Dependency Source framework Type Usage
Okta.AspNetCore SAIF.NetCore.OIDC Transitive Supplies the OIDC/Okta provider integration that OIDC's own registered services (composed by RegisterOidcServices) use for token exchange; this library never references the package directly*.
Microsoft.AspNetCore.Authentication.JwtBearer SAIF.NetCore.AuthService Transitive Supplies JwtBearerDefaults/AddJwtBearer, used directly by RegisterEdgeAPIAuthServices/RegisterCoreAPIAuthServices without this library declaring its own PackageReference to the JwtBearer package*.

API dependencies

This library never makes an outbound HTTP call from its own code; every row below is reached indirectly, through calls this library's registration/middleware code makes into EnvironmentClient's own registered IEnvironmentClient implementation (BaseEnvironmentClient/SecureEnvironmentClient). Each row names the real remote endpoint, the call chain that reaches it, and the condition under which it actually fires. A key distinction runs through every row after the first: calling the refresh check happens on every settings access (ordinary settings via LoadSection/LoadSectionAsync, secure settings via a direct call from RetrieveSecureSetting/RetrieveSecureSettingAsync), but the check's three possible outcomes are not interchangeable: an empty settings cache reloads immediately, with no GET /settings/lastRefreshed probe at all (TestForRefreshSettings returns true before any network call); a non-empty cache before TimeToWaitSeconds (60s) have elapsed since the last probe makes no network call and does not reload; only a non-empty cache at or past that 60s throttle window actually issues the GET /settings/lastRefreshed probe, and even then a reload happens only if that call succeeds and the server's returned timestamp is newer than the client's current LastRefreshed — see Refresh check and cache reload (SAIF.NetCore.EnvironmentClient) for the full three-branch detail.

Endpoint Method Called from Source library Reached via Usage
/v2/tracks/{applicationName}/value (Environment API) GET Register environment client / Register secure environment client — on first resolution of the singleton IEnvironmentClient SAIF.NetCore.EnvironmentClient (src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs) — BaseEnvironmentClient.Setup/GetHostsByTrackWithResilience/GetHostsByTrack RegisterEnvironmentClient/RegisterSecureEnvironmentClient register IEnvironmentClient as a singleton with no factory of this library's own; construction (and therefore Setup()) happens whenever the DI container first resolves the singleton, before any setting lookup. Resolves the application's current track/host assignment so the client knows which Environment API host to address for every later setting lookup.
/settings/lastRefreshed (Environment API) GET Every settings access this library triggers: Register DB connection client step 4 (secure, via GetSecureSetting), Legacy cookie gate middleware step 2 (ordinary, via GetSettingValueAsync) SAIF.NetCore.EnvironmentClient (src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs) — BaseEnvironmentClient.TestForRefreshSettings/CheckForUpdates CheckForUpdates runs on every LoadSection/LoadSectionAsync call (ordinary settings) and is also called directly by RetrieveSecureSetting/RetrieveSecureSettingAsync (secure settings) — not by routing the secure call through LoadSection first. An empty settings cache reloads the entire cache immediately with no GET at all (no probe needed on first access). A non-empty cache issues this GET only once LastCheckForRefresh.AddSeconds(TimeToWaitSeconds) < DateTime.Now (throttled to at most once per 60s); before that it returns immediately with no network call. When the probe does fire, a reload still only happens if the call succeeds and the returned lastRefreshed timestamp is newer than the client's current value — an elapsed interval alone does not force a reload. Whichever branch triggers a reload, CheckForUpdates clears and reloads the entire settings cache, including every previously-known section. See Refresh check and cache reload (SAIF.NetCore.EnvironmentClient) for the full branch-by-branch detail. Cheaply detects whether the server's configuration generation has changed since the client's last reload, so the ordinary- and secure-setting caches are invalidated and reloaded only when stale rather than on every call.
/v2/secureSetting/{applicationName}/{track}/[{section}/]{configKey}/value?systemHashValue={hash} (Environment API) GET Register DB connection client step 4, via IEnvironmentClient.GetSecureSetting(key) on first IDBConnectionClient resolution SAIF.NetCore.EnvironmentClient (src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SecureEnvironmentClient.cs) — RetrieveSecureSetting/GetSecureSettingUrlPart RetrieveSecureSetting/RetrieveSecureSettingAsync call CheckForUpdates() directly first (see row above), then check the local SecureSettingCache keyed on "{section}.{configKey}"; on a cache miss it issues this GET (gated by HasSetting reporting the key exists). Retrieves and decrypts the DB connection service account credentials (a pipe-delimited username/password pair) needed to bootstrap the DB connection client's NTLM authentication.
/v2/settings/{applicationName}/{applicationHost}/[{section}/]value (Environment API) GET Legacy cookie gate middleware step 2, via IEnvironmentClient.GetSettingValueAsync("endpoint", "LegacySessionProvider") in AspNetSessionIdMiddleware.InvokeAsync, and in LegacyBolAuthMiddleware.InvokeAsync if a consuming application manually adds that middleware to its pipeline (this library registers it in DI but never calls UseMiddleware for it itself). This same ordinary-settings pattern is also reached, for different keys, by ConnectionClient's own constructor-time Setup() (invoked from Register DB connection client step 2), which reads the DBConnectionClient section's four settings (ServiceUrl, SqlConnectionEndpoint, PostgreSqlConnectionEndpoint, OracleConnectionEndpoint) via IEnvironmentClient.GetSettingValue. SAIF.NetCore.EnvironmentClient (src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs) — GetSettingValueAsync/GetSettingValue/LoadSettingsAsync/LoadSettings/GetEnvironmentApiUrl GetSettingValueAsync/GetSettingValue call LoadSectionAsync/LoadSection, which run the refresh check above (and can reload an already-known section if the probe fires) and then issue this GET only if that section is not already recorded in the loaded-Sections cache. For the middleware caller: looks up the legacy session provider's redirect endpoint path so the middleware can build the fail-open redirect URL sent to a request missing the legacy cookie. For the DB-client caller: resolves the DB connection service's base URL and per-database-engine connection endpoints needed before credentials can be applied.

Dependency risks and notes

  • This library's Architecture.md-described role of letting an application "only need[ ] to add a reference to this single NuGet package to get access to all SAIF services" is only partially true: it directly references 10 of the other 18 libraries in this repository. Of the remainder, HashUtil is nonetheless transitively available (it arrives automatically via this library's direct reference to SystemHash, which itself directly references HashUtil), but Common, Clients.UC4, LegacyAuth, NHibernate, NtlmApiAuth, Services.Messaging, and WindowsService are not referenced at all, directly or transitively, and must be referenced separately by any consuming application that needs them*.
  • Microsoft.Extensions.DependencyInjection stays pinned at 8.0.0 on the net10.0 target framework while the other framework-adjacent packages (Negotiate, Mvc.NewtonsoftJson) are bumped to 10.0.12, a version-skew inconsistency whose runtime implications were not independently verified**.
  • The five OpenTelemetry.* packages are published to the public nuget.org feed rather than being internal SAIF packages, so their availability depends on external feed connectivity rather than the organization's own package infrastructure*.
  • Enabling ConfigureOpenTelemetry replaces all existing logging providers with OTel's own; an application that also relies on RegisterLoggingService/ConfigureSaifLogger console output will lose it unless the application re-adds a console provider after enabling OTel*.
  • Most internal references are composition-root wiring (constructing/registering the referenced package's own types with no further call from inside this library's own code). EnvironmentClient is a documented exception: RegisterEnvironmentClient/RegisterSecureEnvironmentClient register IEnvironmentClient as a singleton whose construction (and bootstrap track/host lookup) is deferred to first resolution; RegisterDBConnectionClient's factory calls IEnvironmentClient.GetSecureSetting(key) on first IDBConnectionClient resolution; and AspNetSessionIdMiddleware calls IEnvironmentClient.GetSettingValueAsync(key) on every request with no session cookie — none of these are registration-only wiring (see API dependencies above).

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions.csproj
  • src/SAIF.NetCore.ServiceExtensions/Directory.Packages.props
  • src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs, IAppBuilderExtensions.cs, IWebHostBuilderExtensions.cs, IHostBuilderExtensions.cs
  • src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/OpenTelemetryExtensions.cs, OpenTelemetryOptions.cs
  • Architecture.md