This page captures business rules enforced by this library. SAIF.NetCore.ServiceContracts is a contracts-only assembly, so all twelve rules below are enforced by executable code in this library itself (constructors, validating setters, and fluent option methods) — there is no database or SQL involvement for any rule.
BR-001 Raw OIDC credential string must not be null¶
Field
Value
Statement
The raw credential string passed to construct OidcAppCredentials must not be null.
Trigger
A consumer calls new OidcAppCredentials(raw) with raw == null.
Enforcement
OidcAppCredentials..ctor(string) throws ArgumentNullException(nameof(raw)) before attempting to split the string.
Outcome
Construction fails immediately; no OidcAppCredentials instance is produced.
BR-002 Raw OIDC credentials must be two pipe delimited segments¶
Field
Value
Statement
The raw credential string must split into exactly two \|-delimited segments — clientId\|clientSecret — with the first segment assigned to ClientId and the second to ClientSecret.
Trigger
OidcAppCredentials construction with a non-null raw value.
Enforcement
OidcAppCredentials..ctor(string) splits on '\|' and throws ArgumentException("Raw credential parameter does not contain valid credential data.") when the split does not yield exactly two parts; empty segments (e.g. "\|") are accepted.
Outcome
A correctly-shaped string populates both readonly fields; any other shape (0, 1, or 3+ segments) throws and no instance is produced.
BR-004 Shutdown exempt type must be a strict Exception subclass¶
Field
Value
Statement
A ShutdownExemptExceptionType entry's Type must be a strict subclass of System.Exception; Exception itself is rejected because IsSubclassOf is strict.
Trigger
Construction with a non-null Type value.
Enforcement
The private Type setter checks !value.IsSubclassOf(typeof(Exception)) and throws InvalidOperationException("Type must be subclass of Exception.") when the check fails.
Outcome
Only strict subclasses of System.Exception can be registered as shutdown-exempt; typeof(Exception) is always rejected.
BR-005 Shutdown exempt type defaults to always allowed¶
Field
Value
Statement
When no isAllowed predicate is supplied to ShutdownExemptExceptionType, every exception of the exempt type is treated as allowed (handled without triggering shutdown).
Trigger
Construction with isAllowed == null.
Enforcement
ShutdownExemptExceptionType..ctor assigns IsAllowed = isAllowed ?? (ex => true).
Outcome
The exempt-type entry matches unconditionally unless the caller supplies a narrower predicate.
HttpClientOptions defaults to clearing headers after each request (PersistHeadersAfterRequest = false), a 1000 ms retry delay, retries limited to HTTP 401/502/503, and the Default serializer.
Trigger
new HttpClientOptions().
Enforcement
Property initializers on HttpClientOptions set the four defaults listed in the statement.
Outcome
Any IHttpJsonClient configured with unmodified HttpClientOptions behaves per these defaults; interpretation of the values (the retry loop, header clearing) is implemented by SAIF.NetCore.HttpClients*.
BR-009 HttpStatusCodeException defaults to text plain content type¶
Field
Value
Statement
The default HTTP response content type carried by a newly constructed HttpStatusCodeException is text/plain; StatusCode defaults to 0 until the consumer sets it.
Trigger
new HttpStatusCodeException(message[, inner]).
Enforcement
HttpStatusCodeException.ContentType initializes to "text/plain"; StatusCode is an uninitialized int field.
Outcome
Error handlers that render the response body as the declared ContentType fall back to plain text unless the thrower overrides it*.
BR-010 Error handling event args default to unhandled with special actions enabled¶
Field
Value
Statement
A newly raised BeginErrorHandlingEventArgs defaults to Handled = false and FireSpecialActions = true; a subscriber may set either flag to change the outcome.
Trigger
new BeginErrorHandlingEventArgs(ex, container), typically raised by an IWindowsServiceErrorHandler implementation.
Enforcement
BeginErrorHandlingEventArgs property initializers set the two defaults; no null checks are performed on the constructor arguments.
Outcome
Error handling proceeds and special error actions fire by default; the effect of the flags is enforced by the error-handler implementation, not by this library*.
BR-011 Special error action result defaults to not executed¶
Field
Value
Statement
A SpecialErrorActionResult constructed without an explicit status defaults Status to SpecialErrorActionStatus.NotExectued.
Trigger
new SpecialErrorActionResult(title) (status parameter omitted).
Enforcement
SpecialErrorActionResult..ctor(actionTitle, status = default, ex = null) uses the enum's default value for status, which is NotExectued (first declared member).
Outcome
Callers that do not explicitly record an outcome report the action as not executed rather than succeeded or failed.
BR-012 Generic HTTP async overloads are prohibited¶
Field
Value
Statement
The generic DeleteAsync<T>, GetAsync<T>, PatchAsync<T>, PostAsync<T>, and PutAsync<T> members of IHttpJsonClient are prohibited because they are documented as not thread safe; callers must use the non-generic Task<IHttpRequestResult> overloads instead.
Trigger
A consumer calls one of the five generic async overloads.
Enforcement
Each generic overload carries [Obsolete("This method not thread safe and has been depracated. Please use the overload GetAsync(string urlPart, object body).", true)] (wording specific to each verb) on IHttpJsonClient.
Outcome
Compilation fails for any caller of the five generic overloads; only the non-generic overloads are usable.
Contract-declared rules (enforced by implementers)¶
The following semantics are declared by this library's XML documentation comments but are enforced by the implementing libraries, not by code here. They are not local business rules of SAIF.NetCore.ServiceContracts and are listed for traceability only — each implementing library's own published business-rules.md is the authoritative source for verifying these.
CR-001 Result and content deserialization semantics¶
Field
Value
Statement
GetResult<T> deserializes only when the request succeeded (otherwise returns default(T)); GetContent<T> deserializes regardless of status.
Contract member
IHttpRequestResult.GetResult<T>, .GetContent<T>
Trigger
A consumer calls GetResult<T>() or GetContent<T>() on an IHttpRequestResult instance returned by an IHttpJsonClient call.
Enforcement
Declared only by XML documentation comments on IHttpRequestResult in this library; the conditional-deserialization logic is implemented by SAIF.NetCore.HttpClients' HttpRequestResult class, not by code in this package.
Outcome
Callers that use GetResult<T> receive default(T) for an unsuccessful request instead of an attempted deserialization, provided the implementing library honors this documented contract*.
StatusCode is 0 when the request never reached the endpoint; IsSuccessful means a 2xx status.
Contract member
IHttpRequestResult.StatusCode, .IsSuccessful
Trigger
A consumer reads IHttpRequestResult.StatusCode or .IsSuccessful after an IHttpJsonClient call completes.
Enforcement
Declared only by XML documentation comments on IHttpRequestResult in this library; populating these properties correctly is implemented by SAIF.NetCore.HttpClients, not by code in this package.
Outcome
Callers can distinguish a transport failure (StatusCode == 0) from an HTTP-level failure and use IsSuccessful as a 2xx shorthand, provided the implementing library honors this documented contract*.
A consumer calls ISystemHashService.RemoveSystemHashSaltAndValidateLifetime(systemHashValue, expireSeconds, nowBufferSeconds).
Enforcement
Declared only by XML documentation comments on ISystemHashService in this library; the salt-removal, lifetime comparison, and throw behavior are implemented by SAIF.NetCore.SystemHash, not by code in this package.
Outcome
Callers receive the de-salted hash value when it is still within its lifetime, or an exception when it has expired, provided the implementing library honors this documented contract*.
Get(type) computes the hash once (SHA256 per XML doc) and returns the cached value afterwards.
Contract member
ISystemHashService.Get
Trigger
A consumer calls ISystemHashService.Get(SystemType type).
Enforcement
Declared only by XML documentation comments on ISystemHashService.Get in this library; the SHA256 computation and single-compute-then-cache behavior are implemented by SAIF.NetCore.SystemHash, not by code in this package.
Outcome
Repeated calls to Get with the same type return the same cached hash value instead of recomputing it, provided the implementing library honors this documented contract*.
SAIFException.LogDetails are logged but must never be sent back to the client.
Contract member
SAIFException.LogDetails
Trigger
An implementation library's error handler catches a SAIFException (or subclass) carrying a populated LogDetails array.
Enforcement
Declared only by the XML documentation comment on SAIFException.LogDetails in this library; withholding this content from the client response is implemented by SAIF.NetCore.ErrorHandler, not by code in this package.
Outcome
LogDetails content reaches the log sink but is withheld from the HTTP response body, provided the implementing library honors this documented contract*.
HttpStatusCodeException.StatusCode/ContentType control the error response the error handler sends.
Contract member
HttpStatusCodeException
Trigger
Implementation-library code throws an HttpStatusCodeException with a non-default StatusCode and/or ContentType.
Enforcement
Declared only by the XML documentation comments on HttpStatusCodeException in this library; reading these properties and shaping the HTTP response accordingly is implemented by SAIF.NetCore.ErrorHandler, not by code in this package.
Outcome
The client receives the thrower-specified status code and content type instead of a generic error response, provided the implementing library honors this documented contract*.
The logging threshold defaults to the Environment API setting tracingdefaults.logthreshold, overridable per-app with <AppName>.logthreshold.
Contract member
ISaifLogService
Trigger
A logging call is made through an ISaifLogService implementation.
Enforcement
Declared only by XML documentation comments and naming convention associated with ISaifLogService in this library; reading these Environment API settings and applying the threshold is implemented by SAIF.NetCore.Logging, not by code in this package.
Outcome
Log entries below the configured threshold are suppressed, with the per-app override taking precedence over the default, provided the implementing library honors this documented contract*.
IOidcSettings values come from the NetCore_OIDC Environment API setting group.
Contract member
IOidcSettings
Trigger
A consumer reads a property on an IOidcSettings implementation.
Enforcement
Declared only by XML documentation comments and naming convention associated with IOidcSettings in this library; retrieving the values from the NetCore_OIDC setting group is implemented by SAIF.NetCore.OIDC's OidcSettings, not by code in this package.
Outcome
OIDC configuration values are sourced from the NetCore_OIDC Environment API setting group rather than another source, provided the implementing library honors this documented contract*.
IDBConnectionClient requires the calling application to run under an IIS service account to retrieve SQL/Oracle connection strings from DBConnectionsAPI.
Contract member
IDBConnectionClient
Trigger
A consumer calls an IDBConnectionClient member to retrieve a SQL Server or Oracle connection string.
Enforcement
Declared only by XML documentation comments on IDBConnectionClient in this library; the IIS-service-account requirement and the call to DBConnectionsAPI are implemented by SAIF.NetCore.DBConnectionClient, not by code in this package.
Outcome
Calls made outside an authorized IIS service-account context are rejected by DBConnectionsAPI rather than by this contract, provided the implementing library honors this documented contract*.
IIdentityService.AuthenticationScheme is Windows for anonymous requests in IIS.
Contract member
IIdentityService
Trigger
A consumer reads IIdentityService.AuthenticationScheme for an anonymous (unauthenticated) IIS request.
Enforcement
Declared only by XML documentation comments and naming convention associated with IIdentityService in this library; detecting the anonymous IIS case and returning Windows is implemented by SAIF.NetCore.AuthService, not by code in this package.
Outcome
Anonymous IIS requests report Windows as their authentication scheme rather than null or an empty string, provided the implementing library honors this documented contract*.
Rules marked with * in their Outcome field were inferred from XML documentation comments or the implementing library's naming conventions rather than directly observed in this library's compiled code, because the interpretation happens in another package.
CR-001 through CR-010 document declared contract behavior only; their enforcement and runtime verification belong to the implementing library's own business-rules.md, named by the Expected enforcer in each rule's Enforcement field 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.