---
title: SAIF.Framework.Security.EnvironmentApi architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.Security.EnvironmentApi
reference_type: package
---

# SAIF.Framework.Security.EnvironmentApi architecture

SAIF.Framework.Security.EnvironmentApi is the Environment API client layer of the SAIF Security framework. It combines a layered environment/configuration-resolution abstraction (`IEnvironmentService` → `EnvironmentServiceBase` → five host-specific implementations) with a machine/service-account AD authorization subsystem (`MachineSecurityService`/`ADService`) and a thin WCF client (`SecurityServiceClient`) to the centralized `SecurityService` endpoint.

## Responsibilities
- Resolve runtime environment context (host, track, deployment tier, client type) and retrieve configuration settings from a central Environment API HTTP service.
- Cache configuration settings in memory and refresh them on a throttled interval (`AllowRefreshCheckInSeconds`, default 120s).
- Provide AD-group-based machine/service-account authorization via `MachineSecurityService`/`ADService`, including developer-machine detection.
- Provide a thin WCF client (`SecurityServiceClient`) to the centralized `SecurityService` endpoint for AD group-membership lookups, as an alternative to the local/direct `ADService` path.
- Surface host-specific environment details (application host, machine name, client-external/inside-firewall status, local-machine status, current principal) for five distinct hosting contexts.

## Component boundaries
- `IEnvironmentService` (contract, namespace `SAIF.Framework.Security`): primary contract for environment/config/user-context access; defines the public operations consumers rely on.
- `EnvironmentServiceBase` (abstract base class): implements `IEnvironmentService`; performs HTTP calls to the Environment API, holds the in-memory settings cache and refresh logic, and hosts the `IsDeveloperMachine`/`MachineSecurity` cross-cutting authorization logic.
- Host-specific concrete implementations of `EnvironmentServiceBase`, each supplying `ApplicationHost`, `MachineName`, `IsClientExternal`/`IsClientInsideFirewall`/`IsLocalMachine`/`IsWeb`, and `User` for its hosting context:
  - `WebEnvironmentService` (also implements `IWebEnvironmentService`) — ASP.NET web-app context using `HttpContext.Current`.
  - `WindowsEnvironmentService` — console/Windows-service context; resolves host/track from the entry assembly.
  - `WcfEnvironmentService` — WCF service-host context; resolves app id/host from `RequestContext`.
  - `CustomEnvironmentService` — manually-configured context with an explicit host and `CustomEnvironment` enum.
  - `OfficeAddinEnvironmentService` — Office Add-in context with an `OfficeEnvironment` enum.
- `MachineSecurityService` (implements `IMachineSecurityService`, `IDisposable`, namespace `SAIF.Framework.Security.Utilities`): reusable, generic AD group-membership authorization primitive for machine/service accounts, distinct from human-user authorization.
- `ADService` (internal class, namespace `SAIF.Framework.Security.Utilities`): local/direct AD group-membership resolution via `System.DirectoryServices.AccountManagement`/`DirectorySearcher`, used exclusively by `MachineSecurityService`.
- `SecurityServiceClient` (namespace `ClientProxies`): thin WCF client wrapper around the generated `SecurityService.SecurityClient` proxy, exposing `GetUsersByGroup` as a server-side alternative to the local `ADService` path. No call site invoking this class was found elsewhere within this library — it is provided for use by downstream consumers rather than used internally.
- `EnvironmentHost` and `EnvironmentConfigKeys`: supporting utility types — host-name resolution for the Environment API convention, and well-known configuration key-name constants exposed for downstream consumers.
- `SystemHashUtil`/`SystemType` (namespace `SAIF.Services.Common`): salted system-hash generation/validation supporting secure configuration retrieval, built on the framework-inherited `SAIF.HashUtil` package.

## Interaction model
- A consuming application constructs a concrete `*EnvironmentService` for its hosting context (web, Windows, WCF, custom, or Office Add-in).
- On first use, `RefreshConfigurationIfNewer()` issues an HTTP GET to `{EnvironmentApiUrl}/v2/settings/{ApplicationId}/{ApplicationHost}/...`, deserializes the response into `ConfigurationSettings`/`ConfigSetting` DTOs, and caches the result in memory with a throttled refresh check.
- `GetConfigSetting`/`GetConfigSetting<T>` checks the developer-settings-override file first (only honored when `IsDeveloperMachine` is true), then the in-memory cache, then fetches the setting's section from the Environment API if still missing.
- `EnvironmentServiceBase.IsDeveloperMachine` couples the configuration-retrieval layer to the AD-authorization layer: it validates the host name against a `[TV]\d+` tag-number pattern, then calls `MachineSecurityService.IsAuthorized(hostName, "developer_machine_users", isResource:false, recurse:false)`.
- `MachineSecurityService.IsAuthorized` optionally transforms a caller-supplied group name to the SAIF `<Name>Resource`/`<Name>TestResource` convention, then delegates to `ADService.GetUsersByGroup` (recursive LDAP search via `DirectorySearcher`), comparing SAMAccountNames with `$` suffixes trimmed from both sides.
- Independently, `SecurityServiceClient.GetUsersByGroup` opens a `BasicHttpBinding` WCF channel per call to the centralized `SecurityService` endpoint and forwards the group-membership request — an equivalent, server-side alternative to the local `ADService` path, not invoked internally by this library.

The following diagram shows the layered environment-service abstraction and its dependency on the authorization subsystem.

```mermaid
flowchart TD
	IES["IEnvironmentService<br>(contract)"] --> ESB["EnvironmentServiceBase<br>(HTTP calls, caching, refresh)"]
	ESB --> WES["WebEnvironmentService"]
	ESB --> WIN["WindowsEnvironmentService"]
	ESB --> WCF["WcfEnvironmentService"]
	ESB --> CES["CustomEnvironmentService"]
	ESB --> OAS["OfficeAddinEnvironmentService"]
	ESB --> MSS["MachineSecurityService<br>(IsDeveloperMachine check)"]
	MSS --> ADS["ADService<br>(local DirectorySearcher/LDAP)"]
	ESB --> EAPI["Environment API<br>(HTTP /v2/settings, ...)"]
	SSC["SecurityServiceClient<br>(ClientProxies)"] --> SSWCF["SecurityService WCF endpoint<br>(GetUsersByGroup)"]
```

## Sequence diagram
The following diagram shows the primary configuration-retrieval and developer-machine authorization sequence.

```mermaid
sequenceDiagram
	participant Caller
	participant Service as *EnvironmentService
	participant EAPI as Environment API
	participant MSS as MachineSecurityService
	participant AD as ADService (LDAP)
	Caller->>Service: GetConfigSetting(key)
	Service->>Service: RefreshConfigurationIfNewer()
	Service->>EAPI: GET /v2/settings/{ApplicationId}/{ApplicationHost}/...
	EAPI-->>Service: ConfigurationSettings (JSON)
	Service->>MSS: IsAuthorized(hostName, "developer_machine_users")
	MSS->>AD: GetUsersByGroup(groupName, ldap, domain, recurse)
	AD-->>MSS: sAMAccountName[]
	MSS-->>Service: bool
	Service-->>Caller: config value
```

## Design constraints
- `IEnvironmentService` and its abstract base are the only contract layer; there is no dependency-injection container reference in this library — consumers instantiate a concrete `*EnvironmentService` directly for their hosting context.
- The five host-specific implementations are mutually exclusive per hosting context; each supplies its own `ApplicationHost`/`MachineName`/`IsLocalMachine` resolution logic rather than sharing a single runtime-detection mechanism.
- `IMachineSecurityService` is declared `internal` while its implementation `MachineSecurityService` is `public`, so the practical entry point for downstream consumers is the concrete class rather than the interface*.
- `MachineSecurityService.IsAuthorized` fails closed (returns `false`) on any exception during AD lookup, logging only via `Debug.WriteLine` — there is no structured audit/security logging of authorization failures in this library.
- The local `ADService`/`MachineSecurityService` path and the `SecurityServiceClient` WCF path both expose an equivalent `GetUsersByGroup` operation but are not unified — they represent two independent routes to the same underlying AD group-membership data.
- The Environment API base URL must be present as an OS environment variable (`EnvironmentApiUrl`) before any environment-dependent operation executes; its absence throws `MissingEnvironmentUrlVariableException`.
- Config settings default to non-secure retrieval; the secure-retrieval mechanism (`GetSecureConfigSetting`, `SystemHashUtil`) is defined for consumers but has no internal call sites within this library.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Configuration](configuration.md)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

> **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
- SAIF.Framework.Security.EnvironmentApi\Core\Services\IEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\WebEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\WindowsEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\WcfEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\CustomEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\OfficeAddinEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\IWebEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentHost.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentConfigKeys.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\SystemHashUtil.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\MachineSecurityService.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\IMachineSecurityService.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\ADService.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\SecurityServiceClient.cs
- SAIF.Framework.Security.EnvironmentApi\Exceptions\MissingEnvironmentUrlVariableException.cs
- SAIF.Framework.Security.EnvironmentApi\Connected Services\SecurityService\Reference.cs
- SAIF.Framework.Security.EnvironmentApi\app.config
