This page catalogs every business rule this library enforces, identified by stable rule IDs referenced from operations, configuration, security, and API reference pages.
BR-EC-01 The Environment API base URL must be present at construction¶
Field
Value
Statement
The OS environment variable EnvironmentApiUrl must be set. It is the Environment API base URL.
Trigger
Client construction
Enforcement
BaseEnvironmentClient.ServiceUrl field initializer; BaseEnvironmentClient.Setup
Outcome
MissingEnvironmentUrlVariableException if null or empty
BR-EC-03 Track retrieval is retried with linear back-off¶
Field
Value
Statement
Track retrieval is retried EnvironmentClient:GetHostsByTrack:RetryCount times (default 3). A sleep of attempt × RetrySleepMs (default 3000 ms) follows every failed attempt, including the final one, before the next attempt or the terminal exception — e.g. 3 + 6 + 9 = 18 s total with defaults, not just the delays between attempts.
Final EnvironmentClientException with the accumulated log; a RetryCount ≤ 0 means no attempt is made and the exception is thrown immediately with an empty log*
BR-EC-04 A config-file host override requires AD override permission and group membership¶
Field
Value
Statement
A config-file host override is considered only when AppSettings:EnvApiDeveloperOverrideAllowed is not false and the computer is a member of AD group Developer_Machine_Users.
BR-EC-09 A developer override file is honored only when it exists and the machine is a developer machine¶
Field
Value
Statement
A developer settings override file (AppSettings:EnvApiDeveloperSettingsOverride) is honored only if it exists and IsDeveloperMachine() is true. Its entries take precedence over Environment API values for non-secure lookups.
BR-EC-10 Environment API requests identify the caller by host and application name¶
Field
Value
Statement
Requests to the Environment API identify the caller as client NetCore.EnvironmentClient with the resolved ApplicationHost and ApplicationName. The pre-resolution call uses the machine name.
Trigger
Setup
Enforcement
BaseEnvironmentClient.Setup
Outcome
Header/metadata semantics belong to the IHttpJsonClient implementation (unknown here)**
BR-EC-12 Setting keys and section names are lowercased on lookup¶
Field
Value
Statement
BuildDictionaryKey lowercases the entire composed lookup key, so a request key's casing never matters on the lookup side. However, StoreSettingInDictionary lowercases only the section when storing an entry — the setting-key portion is stored exactly as the Environment API returned it (ConfigKey.Key, unmodified). Lookups are therefore guaranteed case-insensitive for the section but not for the key: a stored key whose casing differs from the lowercased request will not match*.
BR-EC-13 Each section is loaded from the Environment API at most once per cache generation¶
Field
Value
Statement
A section is recorded as loaded in Sections only after a fetch succeeds and returns one or more settings; such a successfully-loaded, nonempty section is then skipped (not re-fetched) on every subsequent LoadSection[Async] call until the next global refresh, i.e. at most once per cache generation. A zero-result response is never marked loaded — it is explicitly removed from Sections (self-healing), so it is retried on the very next call, not gated by the global refresh. A thrown exception during a per-section reload (performed by Refresh check and cache reload for every section already in Sections) is not caught at that point: Sections is left unchanged, so a section that was already marked loaded before the refresh remains marked loaded — with no matching Settings entries, because Settings was already cleared — until the next global refresh clears and reloads it again. The root/empty section is never recorded in Sections, so it has no "loaded" state and is reloaded from the Environment API on every call that reaches it, even within the same cache generation.
BR-EC-14 Cache refresh is throttled to at most every 60 seconds¶
Field
Value
Statement
The client checks the Environment API's lastRefreshed timestamp at most once every TimeToWaitSeconds (60 s). If the server timestamp is newer than the client's LastRefreshed, the whole cache is cleared and every known section is reloaded. An empty cache always triggers a load.
BR-EC-17 A section with zero returned settings is retried rather than marked loaded¶
Field
Value
Statement
A section for which the server returns zero settings is not marked as loaded, and is removed if it was previously marked, so it is retried on the next access (fix for the 2026-07-14 incident).
BR-EC-21 SystemType overloads derive the system hash from the injected service¶
Field
Value
Statement
SystemType overloads derive the system hash from the injected ISystemHashService.
Trigger
Secure get by SystemType
Enforcement
BaseEnvironmentClient.GetSecureSetting(configKey, SystemType) and GetSecureSetting(configKey, section, SystemType) overloads (generic <T>, non-generic, and their async counterparts)
Outcome
Hash computed by the SAIF.NetCore.SystemHash implementation via ISystemHashService.Get
BR-EC-23 Secure values are cached per section/key and re-fetched only after a refresh¶
Field
Value
Statement
Secure values are cached per "{section}.{key}" and re-fetched only when the non-secure cache's LastRefreshed is later than the cached fetch time. Null fetches are not cached on first fetch.
BR-EC-30 SecureEnvironmentClient construction requires server enablement or a developer machine¶
Field
Value
Statement
SecureEnvironmentClient can be constructed only when configuration key COREAPIENABLED = "1" (typically env var ASPNETCORE_COREAPIENABLED=1 through the host's prefixed env-var provider) or the machine is a developer machine.
Trigger
Construction of SecureEnvironmentClient
Enforcement
SecureEnvironmentClient..ctor
Outcome
EnvironmentClientException("This server is not enabled for CORE APIs."); this runs after base Setup() has already made network calls
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.