---
title: Register secure environment client
summary: Registers the secure environment client and a hash service keyed on the caller's assembly.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.ServiceExtensions
reference_type: package
operation_id: OP-02
trigger: A consuming application calls RegisterSecureEnvironmentClient(Type type) during service configuration.
---

# Register secure environment client

This operation registers the secure `IEnvironmentClient` implementation, enabling secure-setting retrieval gated by a per-assembly system hash. It underlies [App startup configure services](app-startup-configure-services.md), [Register for Windows service](register-for-windows-service.md), and [Console host bootstrap](console-host-bootstrap.md).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-02 |
| **Trigger** | Application startup code calls `RegisterSecureEnvironmentClient(Type type)` on `IServiceCollection`. |
| **Inputs** | `type` — the caller's own type, used to resolve its containing assembly. |
| **Outputs** | Registers `IEnvironmentClient → SecureEnvironmentClient` and an `ISystemHashService` keyed on `type`'s assembly. |
| **Primary components** | `IServiceCollectionExtensions.RegisterSecureEnvironmentClient` |
| **Entry point** | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` (L82–92) |

## Steps

1. Perform the same `AddHttpContextAccessor`/`ISystemWrapper`/`IHostResolver`/`IHttpJsonClient` registrations as [Register environment client](register-environment-client.md) steps 1–3.
2. Register Singleton `IEnvironmentClient → SecureEnvironmentClient` ([BR-SE-03](../business-rules.md#br-se-03-secure-mode-system-hash-is-computed-from-the-caller's-assembly))

   > **Origin**: `SecureEnvironmentClient`'s secure-setting and caching behavior is implemented in [`Get secure setting`](../../saif-netcore-environmentclient/operations/get-secure-setting.md) and [`Secure setting cache`](../../saif-netcore-environmentclient/operations/secure-setting-cache.md) (`SAIF.NetCore.EnvironmentClient`); this step only registers the type-based singleton descriptor — construction is deferred to first resolution of `IEnvironmentClient`, not performed during registration.
3. Register a Singleton `ISystemHashService` factory that constructs `new SystemHashService(Assembly.GetAssembly(type))` ([BR-SE-03](../business-rules.md#br-se-03-secure-mode-system-hash-is-computed-from-the-caller's-assembly))
   - If `type` is `null`: `Assembly.GetAssembly` throws `ArgumentNullException` (inferred*).

   > **Origin**: `SystemHashService`'s hash computation is implemented in [`Compute unsalted system hash`](../../saif-netcore-systemhash/operations/compute-unsalted-system-hash.md) and [`Compute salted system hash`](../../saif-netcore-systemhash/operations/compute-salted-system-hash.md) (`SAIF.NetCore.SystemHash`); this step only registers the factory delegate — the factory runs, and `SystemHashService` is constructed, at first resolution of `ISystemHashService`, not during registration.

## Process flow

This diagram shows the one-time DI registration sequence performed when `RegisterSecureEnvironmentClient(type)` is called during service configuration; construction of `SecureEnvironmentClient` and `SystemHashService` is deferred to first resolution, not shown as occurring here.

```mermaid
flowchart TD
    Start([RegisterSecureEnvironmentClient called]) --> S1[Register shared infra services]
    S1 --> S2["Register IEnvironmentClient descriptor<br>as SecureEnvironmentClient"]
    S2 --> S3["Register ISystemHashService factory delegate<br>(captures type, not yet invoked)"]
    S3 --> EndOk(["Registration call returns; nothing constructed yet"])
    EndOk -.->|First resolution of ISystemHashService| R1{type is null?}
    R1 -->|Yes| EndErr(["Factory throws ArgumentNullException<br>from Assembly.GetAssembly(type)"])
    R1 -->|No| R2["Factory constructs new SystemHashService<br>via Assembly.GetAssembly(type)"]
```

## Failure and edge-case behavior
- `type == null` causes `Assembly.GetAssembly(type)` to throw `ArgumentNullException` when the hash-service factory executes (inferred*).

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.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
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs`
