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.
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)
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)
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*.
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.
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**.
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.
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.
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.
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.