Skip to content

SAIF.NetCore.Clients.UC4 business rules

This page captures business rules enforced by this library.

BR-UC4-01 Required settings must exist at construction

Field Value
Statement uc4coreapi:url and uc4coreapi:schedulejobroute must both exist in the Environment API section uc4coreapi, or construction of UC4Client fails.
Trigger UC4Client constructor runs (DI resolution or direct new).
Enforcement UC4Client..ctor calls EnsureSettingExists for each key, which calls IEnvironmentClient.HasSetting; a false result throws NotSupportedException.
Outcome Construction aborts with NotSupportedException if either key is absent; the client cannot be used in that environment.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs

BR-UC4-02 Settings existence is validated independently of value content

Field Value
Statement An empty string value for uc4coreapi:url or uc4coreapi:schedulejobroute passes the existence check and construction succeeds; the value is not validated for shape or non-emptiness.
Trigger Construction reads the setting value after the existence check has passed.
Enforcement UC4Client..ctor reads GetSettingValue, which returns ConfigValue?.Value ?? "" with no further validation.
Outcome An empty ServiceUrl or ScheduleJobEndpoint is accepted at construction and fails later, during ScheduleJob, with UriFormatException or a malformed route.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs (declares GetSettingValue's ConfigValue?.Value ?? "" behavior)

BR-UC4-03 Job scheduling URL is built by direct string concatenation

Field Value
Statement The request URL for scheduling a job is ScheduleJobEndpoint + jobname, built by direct string concatenation with no URL-encoding of jobname.
Trigger ScheduleJob(appname, jobname) is called.
Enforcement UC4Client.ScheduleJob builds $"{ScheduleJobEndpoint}{jobname}" and passes it to IHttpJsonClient.PostAsync.
Outcome A jobname containing URL-reserved characters (/, ?, #, spaces) can route to an unintended endpoint or be rejected by the server*.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs

BR-UC4-04 Caller identity is sent via fixed and caller-supplied headers

Field Value
Statement Every scheduling request carries Client-Name = the running machine name, Application-ID = the caller-supplied appname, and Client-User = the fixed string "SAIF.NetCore.Clients.UC4".
Trigger Init runs on the first ScheduleJob call, calling SetClientInfo; headers are attached on every subsequent POST.
Enforcement UC4Client.Init calls IHttpJsonClient.SetClientInfo(ServiceUrl, ClientName, Environment.MachineName, appName); HttpJsonClient.CreateRequest attaches the headers from the stored ClientInfo.
Outcome The UC4 API receives a consistent, caller-identifiable set of headers for every request from a given client instance.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (declares SetClientInfo and CreateRequest, which attach the headers)

BR-UC4-05 Application ID cannot be null

Field Value
Statement appname cannot be null; a null value throws ArgumentNullException during initialization, inherited from the shared ClientInfo construction logic in SAIF.NetCore.HttpClients.
Trigger Init(appName) constructs a ClientInfo with the supplied appName.
Enforcement ClientInfo's constructor (in SAIF.NetCore.HttpClients) throws ArgumentNullException when any constructor argument, including applicationId, is null.
Outcome A null appname on the first ScheduleJob call throws before any HTTP request is attempted; IsConfigured remains false so the next call retries Init.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/ClientInfo.cs (declares the constructor that throws ArgumentNullException)

BR-UC4-06 Client identity is fixed on first use

Field Value
Statement The appname supplied on the first ScheduleJob call becomes the fixed Application-ID for every subsequent call on that same UC4Client instance; later calls with a different appname do not change it.
Trigger A second or later ScheduleJob call passes a different appname than the first call.
Enforcement UC4Client.ScheduleJob only calls Init when IsConfigured == false; once true, appname on subsequent calls is accepted by the method signature but never applied.
Outcome Consumers that reuse a single injected UC4Client across multiple logical applications will silently misreport Application-ID after the first call*.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs

BR-UC4-07 IsConfigured has a public setter that bypasses initialization

Field Value
Statement IsConfigured has a public setter; external code can set it to true before any ScheduleJob call, skipping Init and the underlying SetClientInfo call entirely.
Trigger External code sets client.IsConfigured = true directly.
Enforcement UC4Client.IsConfigured { get; set; } has no guard against external mutation; ScheduleJob trusts the flag unconditionally.
Outcome The subsequent POST fails with ClientNotInitializedException from HttpJsonClient.ValidateInitialization, unless the injected IHttpJsonClient was separately initialized elsewhere.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (declares ValidateInitialization and ClientNotInitializedException)

BR-UC4-08 Scheduling requests retry automatically on specific transient status codes

Field Value
Statement A scheduling POST that returns status 401, 502, or 503 is retried automatically, up to 3 times, with a fixed delay between attempts.
Trigger The UC4 API responds with one of the retryable status codes.
Enforcement HttpJsonClient.ExecuteAsync (in SAIF.NetCore.HttpClients) checks the response status against RetryOnStatusCodes (default {401, 502, 503}) and retries up to retries (3) times with RetryDelayInMs (default 1000 ms) between attempts.
Outcome Whether a retry after a 502/503 that the UC4 API actually processed can submit a duplicate job depends on whether the UC4 Core API's schedule endpoint is idempotent, which is unknown**.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (declares ExecuteAsync's retry loop); src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/HttpClientOptions.cs (declares the RetryOnStatusCodes/RetryDelayInMs defaults)

BR-UC4-09 Scheduling failures are returned, not thrown

Field Value
Statement A non-success HTTP response from the UC4 API is returned to the caller as IHttpRequestResult.IsSuccessful = false; it is never raised as a thrown exception from ScheduleJob itself.
Trigger The UC4 API responds with a non-success status after all retries are exhausted.
Enforcement HttpJsonClient.ExecuteAsync builds an HttpRequestResult with IsSuccessful set from the response status and returns it; it does not throw for HTTP-level failures.
Outcome Consumers that do not check IsSuccessful will silently treat a failed scheduling attempt as successful.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs (call site); src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (declares ExecuteAsync's HttpRequestResult construction)

BR-UC4-10 Scheduled jobs start with an empty JSON object

Field Value
Statement Every scheduling POST carries an empty JSON object ({}), with no job parameters, schedule time, or metadata passed through this API surface.
Trigger ScheduleJob builds the POST request.
Enforcement UC4Client.ScheduleJob calls IHttpJsonClient.PostAsync($"{ScheduleJobEndpoint}{jobname}", new { }), which RestSharp serializes to the JSON object {}; jobname is only present in the URL path, never in the body.
Outcome UC4 jobs triggered through this client must be pre-configured on the UC4/Automic side with all parameters; this client can only start them by name.
Source src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs

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.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4.csproj
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Constants.cs
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/IUC4Client.cs
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs
  • src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs — declares the HasSetting/GetSettingValue behavior enforced by BR-UC4-01/BR-UC4-02.
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs — declares SetClientInfo, ValidateInitialization, and ExecuteAsync's retry/result behavior enforced by BR-UC4-04, BR-UC4-07, BR-UC4-08, BR-UC4-09.
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/ClientInfo.cs — declares the constructor behavior enforced by BR-UC4-05.
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/HttpClientOptions.cs — declares the retry defaults referenced by BR-UC4-08.