# SAIF.Platform.Azure

Wires Azure App Configuration and Feature Management into a Forge service, plus `Azure.Identity`-based credential defaults for talking to Azure.

## Getting started

Register and use Azure defaults in your service:

```csharp
builder.AddAzureDefaults(options =>
{
    options.Prefixes = ["team:*", "SAIF:*", "services:*", "OTEL_*", "ConnectionStrings:*"];
    options.FeatureFlagRefreshInterval = TimeSpan.FromMinutes(5);
});

// ...

app.UseAzureDefaults();
```

- `AddAzureDefaults()` — calls `ConfigureAzureAppConfiguration()` and registers scoped feature management (`AddScopedFeatureManagement()`).
- `UseAzureDefaults()` — adds the Azure App Configuration middleware (`UseAzureAppConfiguration()`) so configuration and feature flags refresh mid-request. Must be called in the request pipeline.

`ConfigureAzureAppConfiguration()`/`UseAzureAppConfiguration()` are no-ops when `AppConfigurationEndpoint` isn't present in configuration, so the package is safe to add to services that don't yet have an App Configuration store provisioned. `AddAzureDefaults()` still registers scoped feature management (`AddScopedFeatureManagement()`) unconditionally, so local configuration-backed feature management remains available even without a remote App Configuration store; only the remote Azure App Configuration-backed flags and refresh depend on the endpoint.

## Azure App Configuration wiring

`ConfigureAzureAppConfiguration()` (called by `AddAzureDefaults()`, or usable directly) connects to the endpoint in `AppConfigurationEndpoint` using `DefaultAzureCredential`, and:

- Loads each configured key prefix twice — once with a null label (global) and once labeled with the current `IHostEnvironment.EnvironmentName` (environment overrides).
- When `ProjectId` is set in configuration, also loads `{projectId}:*` keys (null and environment labels) and trims the `{projectId}:` prefix, so `{projectId}:MyKey` in App Configuration resolves to `MyKey` locally.
- Resolves Key Vault references using the same `DefaultAzureCredential`.
- Loads feature flags, scoped by `{projectId}` (base defaults) and `{projectId}/{environment}` (overrides) when `ProjectId` is set, refreshed on the interval in `AzureConfigurationOptions.FeatureFlagRefreshInterval`.
- Registers `ConfigureRefresh(refreshOptions => refreshOptions.RegisterAll())`, so all loaded keys are watched for change-based refresh.

## `AzureConfigurationOptions`

| Member | Type | Default | Purpose |
|---|---|---|---|
| `Prefixes` | `string[]` | `["team:*", "SAIF:*", "services:*", "OTEL_*", "ConnectionStrings:*"]` | Key prefixes to load from Azure App Configuration. Each entry is loaded with both a null label and the current environment's label. |
| `FeatureFlagRefreshInterval` | `TimeSpan?` | `null` (treated as 5 minutes) | How frequently feature flags are refreshed from Azure App Configuration. |

## Related packages

- `SAIF.Platform` — the base service-defaults package this one extends with Azure-specific configuration. Take a dependency on `SAIF.Platform` first, then layer `SAIF.Platform.Azure` on top for App Configuration and feature flags. See [`../SAIF.Platform/README.md`](../SAIF.Platform/index.md).

---

[View source on GitHub](https://github.com/saif-corp/forge/blob/main/src/dotnet/SAIF.Platform.Azure/README.md)
