---
title: Determine developer-machine status
summary: Decide whether the current host may use developer-only behavior.
status: draft
owner: SAIF Framework
last_reviewed: 2026-07-30
library: SAIF.Framework.Security.EnvironmentApi
reference_type: package
operation_id: OP-ENV-006
trigger: Host resolution or override lookup reads IsDeveloperMachine
---

# Determine developer-machine status

This operation gates every piece of developer-only behavior in the library, including override-file usage and per-host development fallbacks. It first checks the host's naming convention as a cheap filter, and only performs the more expensive LDAP bootstrap and AD membership check when that filter passes.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-ENV-006 |
| **Trigger** | Host resolution or override lookup needs `IsDeveloperMachine` |
| **Inputs** | DNS host name, bootstrap LDAP/domain settings |
| **Outputs** | Memoized `bool` |
| **Primary components** | `EnvironmentServiceBase.IsDeveloperMachine`, `EnvironmentServiceBase.IsMachineTagNumber`, `EnvironmentServiceBase.MachineSecurity`, `EnvironmentServiceBase.DeveloperSettingsFile` |
| **Entry point** | `SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs` |

## Steps

1. If `_isDeveloperMachine` already holds a value, return it immediately so repeated checks never repeat the DNS, LDAP, or AD work.
2. Read the local host name with `Dns.GetHostName()` and require its first segment to match `^[TV]\d+$`. If it does not match, return `false` without performing any AD lookup at all ([BR-005](../business-rules.md#br-005-developer-machine-classification-requires-tag-number-host-and-ad-membership)).
3. When the host name passes that filter, bootstrap `MachineSecurityService` the first time it is needed by reading `ad.ldap.host`, `ad.ldap.internal.root`, and `ad.internal.domain` from the Environment API and combining them into the LDAP path ([BR-002](../business-rules.md#br-002-environment-api-base-url-must-be-present)).
   - Download each bootstrap value as an individual global setting.
   - Combine `ldapHost` and `internalRoot` into the final LDAP path used for AD lookups.

   > **Origin**: Step 3 calls [Retrieve a global configuration setting](retrieve-global-configuration-setting.md) three times to assemble the authorization context before any AD query runs.
4. Set `groupName` to `developer_machine_users` and call the machine authorization workflow with `isResource: false` and `recurse: false` ([BR-005](../business-rules.md#br-005-developer-machine-classification-requires-tag-number-host-and-ad-membership), [BR-006](../business-rules.md#br-006-machineservice-account-authorization-via-ad-group-membership)).
   - Keep the unsuffixed group name, because developer machines do not follow the production/non-production resource-group naming convention.
   - Return the authorization result directly as the developer-machine decision.

   > **Origin**: Step 4 is expanded in [Authorize a machine or service account](authorize-a-machine-or-service-account.md) and runs on behalf of this check.
5. Cache the resulting Boolean in `_isDeveloperMachine` for the remaining lifetime of the service instance.
6. `DeveloperSettingsFile` depends on this cached result before it will honor `EnvApiDeveloperSettingsOverride`, so a non-developer host can never activate local configuration overrides ([BR-004](../business-rules.md#br-004-developer-settings-override-requires-developer-machine-status)).

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Consumer reads IsDeveloperMachine]) --> Cached{Memoized value exists?}
	Cached -->|Yes| ReturnCached([Return cached value])
	Cached -->|No| Host[Read DNS host name]
	Host --> Pattern{Matches tag-number pattern?}
	Pattern -->|No| ReturnFalse([Return false])
	Pattern -->|Yes| Bootstrap[Load LDAP and domain settings]
	Bootstrap --> Auth[Authorize host in developer_machine_users]
	Auth --> Save[Cache result]
	Save --> End([Return developer-machine status])
```

## Failure and edge-case behavior

- A host name that does not match the tag-number convention short-circuits before any AD lookup runs, so most production hosts never touch this network path.
- Bootstrap setting retrieval can fail before the authorization call is ever made, since the LDAP path depends on three separate global-setting reads succeeding.
- The result is memoized for the lifetime of the service instance, so a later change to AD group membership or environment settings is not observed until a new instance is created.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Configuration](../configuration.md)
- [Security and authorization](../security-authorization.md)

## Sources
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\MachineSecurityService.cs
