Skip to content

SAIF.NetCore.DBConnectionClient business rules

This page captures business rules enforced by this library.

BR-DBC-01 Configuration keys source the service URL and endpoint segments

Field Value
Statement The service URL and the three endpoint path segments come from configuration section DBConnectionClient (keys ServiceUrl, SqlConnectionEndpoint, PostgreSqlConnectionEndpoint, OracleConnectionEndpoint).
Trigger Construction
Enforcement ConnectionClient.Setup reads all four keys through IEnvironmentClient.GetSettingValue; keys are declared in ConnectionClientKeys.
Outcome Values are stored in protected properties (ServiceUrl, SqlEndpoint, PostgreSqlEndpoint, OracleEndpoint) used by every subsequent request.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-02 Every request identifies itself via client-info headers

Field Value
Statement Every request identifies itself with client user "DBConnectionClient", the host's ApplicationHost, and ApplicationName.
Trigger Construction
Enforcement ConnectionClient.Setup calls IHttpJsonClient.SetClientInfo with these values.
Outcome Identification headers are applied to all subsequent calls.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-03 NTLM authentication, defaulting to process identity

Field Value
Statement Calls to the DBConnectionAPI authenticate with NTLM — current process identity by default, replaced by explicit service-account credentials when SetupClientCredentials is called.
Trigger Construction; credential setup
Enforcement ConnectionClient.Setup calls SetNtlmAuthentication(); ConnectionClient.SetupClientCredentials calls SetNtlmAuthentication(username, password).
Outcome NTLM authentication is configured on the HTTP client.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-04 Cache keys are engine-prefixed

Field Value
Statement Cache keys are engine-prefixed: SQL_{server}_{instance}_{user}, POSTGRES_{instance}_{user}, ORA_{instance}_{user}.
Trigger Each Get*Connection call
Enforcement GetSqlServerConnection, GetPostgreSqlServerConnection, GetOracleConnection build the respective key before cache lookup.
Outcome Distinct cache entries per database engine and target.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-05 PostgreSQL host is managed client-side

Field Value
Statement PostgreSQL server/host is not managed by the API: lookup uses only instance and user, and the returned template's {SERVER} placeholder is replaced by the caller-supplied server.
Trigger GetPostgreSqlServerConnection
Enforcement ConnectionClient.GetPostgreSqlServerConnection omits server from the cache key and URL path, then substitutes {SERVER} in the retrieved template.
Outcome The host is injected client-side; the template is cached host-independent, so different hosts sharing instance and user reuse one fetch.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-06 Successful retrievals are cached for instance lifetime; failures are not

Field Value
Statement A successfully retrieved connection string is cached for the life of the instance and never refreshed; failed retrievals are not cached; cache access is serialized.
Trigger Any Get*Connection call
Enforcement ConnectionClient.GetCachedConnectionString adds to the cache only after a successful retrieval, under lock(_connections).
Outcome One fetch per key per instance; refreshing a cached value requires replacing the ConnectionClient instance — restarting the usual singleton-hosted process is the typical way to do this. Rotating the outbound service-account credential (dbconnectionclient:connectionservicecreds) does not by itself clear the cache, because that credential only affects the NTLM identity presented on the next uncached request.*
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-07 Backoff configuration must cover all retry attempts

Field Value
Statement RetrieveBackoffDelays must have at least MaxRetrieveAttempts − 1 entries.
Trigger Start of every retrieval
Enforcement ConnectionClient.ValidateBackoffConfiguration checks the invariant before any HTTP call.
Outcome InvalidOperationException is thrown before any HTTP call if the invariant does not hold.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-08 Bounded retry with fixed backoff

Field Value
Statement At most MaxRetrieveAttempts (default 4) of this client's own outer attempts are made, with backoff 2s → 3s → 5s between transient failures (maximum ~10 s of outer waiting). This is not an end-to-end bound: with the standard registered IHttpJsonClient transport, each outer attempt can itself make up to four inner HTTP requests with up to three additional 1-second inner sleeps, so total attempts, waiting, and elapsed time can exceed these outer figures. See Retrieve with retry.
Trigger Transient failure
Enforcement ConnectionClient.RetrieveConnectionString loops up to MaxRetrieveAttempts, using _defaultRetrieveBackoffDelays.
Outcome Retry, then throw the last transient DBClientException with an "(attempt n/N)" annotation.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-09 401/403/404 are permanent failures

Field Value
Statement HTTP 401, 404, and 403 are permanent for this client's own outer loop: the request fails immediately without an outer retry, even if ErrorException is set. This outer fail-fast behavior does not guarantee that the server received only one authentication attempt — with the standard registered IHttpJsonClient transport, a 401 is also one of its default inner-retry status codes, so the same credentials can already have been re-presented up to three additional times before this outer check ever observes the result.
Trigger Non-success response
Enforcement ConnectionClient.RetrieveConnectionString checks these statuses before the transient-failure test.
Outcome DBClientException is thrown ("denied access" / "not found" with service message / "access denied").
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-10 503 or network-level failure is transient

Field Value
Statement A failure is transient when the status is 503, or the request failed with a non-null ErrorException (network-level failure).
Trigger Non-success response
Enforcement ConnectionClient.RetrieveConnectionString classifies the outcome and retries per BR-DBC-08.
Outcome Retry is attempted; the inner exception is preserved; a null message falls back to "(no details)".
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-11 Other failures and empty bodies fail immediately

Field Value
Statement Any other non-success status (for example, 500 without an exception) and a successful-but-empty body fail immediately.
Trigger Response
Enforcement ConnectionClient.RetrieveConnectionString throws without retry for these cases.
Outcome DBClientException is thrown ("Failed to retrieve database connection string: {connectionName} (attempt {attempt}/{MaxRetrieveAttempts})", with ". Service Error Message: {ErrorMessage}" appended when present, for the non-success case; "Database connection string is null: {connectionName} (attempt {attempt}/{MaxRetrieveAttempts})" for the empty-body case).
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

BR-DBC-12 Legacy special-character token is decoded

Field Value
Statement The token ZSPECIALCHAR in a returned connection string is decoded to the ASCII BEL control character (char)7.
Trigger Successful retrieval
Enforcement ConnectionClient.HandleLegacyConnectionString performs a literal string replacement.
Outcome The decoded string is returned and cached.
Source src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

Notes

  • No rules are inherited from a dependency base class: SAIFException (ServiceContracts) adds no behavior beyond Exception constructors.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIFException.cs