# Example: NCore configuration

`configuration.md` records every configuration key a library reads, how it is
retrieved, and which class consumes it. For a modern .NET (NCore) library, doc
gen documents the `IConfiguration` keys (`appsettings.json` and any other
provider), `IEnvironmentClient` settings, and environment variables, and it
never produces the .NET Framework `AppSettings` / `Web.config` section. The
page lives at `docs/libraries/<slug>/configuration.md` and is conditional: it
exists only when configuration access is detected.

## What reviewers should check

- The frontmatter `title` and the H1 are both `Configuration settings`, as on
  every library configuration page.
- There is no `## AppSettings (Web.config)` section, and the text never uses
  `ConfigurationManager.AppSettings`, `IEnvironmentService`, `App.config`, or
  `GetConfigSetting`. An ncore library has none of them.
- `## appsettings.json and IConfiguration` uses `Section:Key` notation, marks
  exactly the keys the code requires as `Required`, and records the code
  default for every optional key.
- Environment API keys read with a section argument are written as
  `<section>:<key>`, and the secure setting records the decryption input
  (`SystemType`), never a value.
- `## Environment variables` states the scope read (process, machine, or
  both), the accepted values, the default when unset, and when the variable is
  read. The same variable is cross-referenced from the `Feature flags` table
  on the service registration page.
- Options bound with `Configure<T>` have one row per bound property, and the
  section name matches the one in the service registration page's options
  table.
- Sections with no rows are omitted entirely. This library has no developer
  override file and no database connection of its own, so neither section
  appears.
- Transitive configuration names the package that needs each key, and the `†`
  marker is followed by the canonical note box immediately before `## Sources`.
- Configuration dependencies state the concrete failure behavior, such as the
  exception type or what the library does instead.

## Example

The document below is a complete, correct `configuration.md` for a fictional
NCore library.

[View rendered example](rendered/libraries/saif-ncore-messaging/configuration.md) — the same document as a real page, so you can compare rendering as well as source.

````markdown
---
title: Configuration settings
summary: Configuration keys consumed by this library, retrieval methods, and runtime dependencies.
status: draft
owner: Messaging Platform Team
last_reviewed: 2026-10-21
library: SAIF.NCore.Messaging
reference_type: package
---

# Configuration settings

SAIF.NCore.Messaging reads ten settings through three mechanisms: seven keys
under the `Messaging` section of `IConfiguration`, bound to `MessagingOptions`
and `OutboxOptions`; two values from `IEnvironmentClient`, one plain and one
secure, applied to `MessagingOptions` after binding; and one process
environment variable that disables the outbox dispatcher. Only
`Messaging:ServiceName` is mandatory. The configuration keys are read when an
options object is first resolved, and the environment variable is read once,
while `AddSaifMessagingOutbox` runs at startup.

## Configuration retrieval methods

| Method | Class / Interface | Namespace | Usage pattern |
| --- | --- | --- | --- |
| `Configure<T>` | IServiceCollection | Microsoft.Extensions.DependencyInjection | `AddSaifMessaging` binds the `Messaging` section to `MessagingOptions`, and `AddSaifMessagingOutbox` binds `Messaging:Outbox` to `OutboxOptions`. |
| GetSettingValue | IEnvironmentClient | SAIF.NetCore.Environment | Called by `ConfigureMessagingOptions.PostConfigure` with section `Messaging` and key `TopicPrefix`, only after `HasSetting` returns true. |
| HasSetting | IEnvironmentClient | SAIF.NetCore.Environment | Called by `ConfigureMessagingOptions.PostConfigure` to test for `Messaging:TopicPrefix` before reading it. |
| GetSecureSetting | IEnvironmentClient | SAIF.NetCore.Environment | Called by `ConfigureMessagingOptions.PostConfigure` with section `Messaging`, key `ConnectionString`, and the `SystemType` argument; decryption happens inside the environment client. |
| GetEnvironmentVariable | Environment | System | Called by `AddSaifMessagingOutbox` with the variable name and no target, so the process scope is read. |

## Environment API settings

Settings retrieved via `IEnvironmentClient` (centralized environment configuration client).

| Setting key | Method | Data type | Purpose | Consuming class | Source |
| --- | --- | --- | --- | --- | --- |
| `Messaging:TopicPrefix` | `GetSettingValue` | String | Prefix prepended to every topic name so lower environments do not share topics with production. | ConfigureMessagingOptions | src/SAIF.NCore.Messaging/Options/ConfigureMessagingOptions.cs |

## appsettings.json and IConfiguration

Settings read through `IConfiguration` (`appsettings.json`, `appsettings.<Environment>.json`, environment variables, and any other configured provider).

| Setting key | Required | Default value | Retrieval | Purpose | Consuming class | Source |
| --- | --- | --- | --- | --- | --- | --- |
| `Messaging:ServiceName` | Yes | None | `Configure<T>` | Name stamped on every outgoing message envelope as its source. `MessagePublisher` throws when the value is empty. | MessagePublisher | src/SAIF.NCore.Messaging/Options/MessagingOptions.cs |
| `Messaging:DefaultTopic` | No | `saif.events` | `Configure<T>` | Topic used when `Publish` is called without an explicit topic. | MessagePublisher | src/SAIF.NCore.Messaging/Options/MessagingOptions.cs |
| `Messaging:MaxDeliveryAttempts` | No | `5` | `Configure<T>` | Handler attempts for a message before it is dead-lettered. | MessageHandlerDispatcher | src/SAIF.NCore.Messaging/Options/MessagingOptions.cs |
| `Messaging:PublishTimeoutSeconds` | No | `30` | `Configure<T>` | Time limit for one send to the message bus. | ServiceBusClientAdapter | src/SAIF.NCore.Messaging/Options/MessagingOptions.cs |
| `Messaging:Outbox:PollIntervalSeconds` | No | `10` | `Configure<T>` | Seconds between outbox dispatch cycles. | OutboxDispatchService | src/SAIF.NCore.Messaging/Options/OutboxOptions.cs |
| `Messaging:Outbox:BatchSize` | No | `100` | `Configure<T>` | Maximum pending outbox rows read in one dispatch cycle. | OutboxDispatchService | src/SAIF.NCore.Messaging/Options/OutboxOptions.cs |
| `Messaging:Outbox:RetentionHours` | No | `72` | `Configure<T>` | Hours a dispatched outbox row is kept before `SqlOutboxStore` purges it. | SqlOutboxStore | src/SAIF.NCore.Messaging/Options/OutboxOptions.cs |

## Environment variables

| Variable | Scope read | Accepted values | Default when unset | Effect | Source |
| --- | --- | --- | --- | --- | --- |
| `SAIF_MESSAGING_DISABLE_DISPATCH` | Process | `true` or `false`, case-insensitive; any other value is treated as `false` | `false` | When `true`, `AddSaifMessagingOutbox` does not register `OutboxDispatchService`. The process still writes outbox rows but never dispatches them. The value is read once at startup, so a change needs a restart. | src/SAIF.NCore.Messaging/Extensions/ServiceCollectionExtensions.cs |

## Secure settings

Settings that require decryption or credential retrieval.

| Setting key | Encryption method | Purpose | Consuming class | Source |
| --- | --- | --- | --- | --- |
| `Messaging:ConnectionString` | Decrypted by `IEnvironmentClient.GetSecureSetting` using the `SystemType` argument `SystemType.Messaging` | Connection string for the service bus namespace used by `ServiceBusClientAdapter`. | ConfigureMessagingOptions | src/SAIF.NCore.Messaging/Options/ConfigureMessagingOptions.cs |

## Transitive configuration (from dependencies)

Settings required at runtime by referenced libraries or packages, not directly consumed by this library's code.

| Setting key | Method | Source dependency | Dependency type | Purpose |
| --- | --- | --- | --- | --- |
| `AppSettings:ApplicationHost` | `IConfiguration` | SAIF.NetCore.ServiceExtensions | NuGet | Names the host the environment client requests settings for, so every `IEnvironmentClient` call made by this library resolves against the right host†. |
| `AppSettings:ApplicationName` | `IConfiguration` | SAIF.NetCore.ServiceExtensions | NuGet | Names the application the environment client requests settings for†. |

## Configuration dependencies

| Dependency | Type | Required at | Impact if missing |
| --- | --- | --- | --- |
| IEnvironmentClient | service | Runtime, when `MessagingOptions` is first resolved | `ConfigureMessagingOptions` cannot be constructed, so resolving `IOptions<MessagingOptions>` throws `InvalidOperationException` and `MessagePublisher` and `ServiceBusClientAdapter` fail to resolve. |
| `Messaging` section in appsettings.json | section | Runtime, when `MessagePublisher` is first resolved | `MessagingOptions` keeps its code defaults, but `ServiceName` has none, so `MessagePublisher` throws `InvalidOperationException` on first resolution and nothing can be published. |
| `Messaging:ConnectionString` secure setting | secure setting | Runtime, when `ServiceBusClientAdapter` is first resolved | The connection string stays unset and `ServiceBusClientAdapter` throws `InvalidOperationException` on first resolution; no message is sent or received. |
| `Messaging:TopicPrefix` setting | setting | Runtime, when `MessagingOptions` is first resolved | `HasSetting` returns false and the prefix stays empty, so topic names are used unprefixed. |
| `IOutboxConnectionFactory` | service | Runtime, on each outbox dispatch cycle and each outbox publish | `SqlOutboxStore` cannot be constructed. `OutboxDispatchService` logs the failure and retries after the poll interval, and `MessagePublisher` throws `InvalidOperationException` when it resolves the outbox store. |

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Service registration](service-registration.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `†` are derived from dependency library
> documentation via the Legends CLI. They describe inherited behavior from the
> indicated origin library and should be verified if the dependency version changes.

## Sources
- src/SAIF.NCore.Messaging/Extensions/ServiceCollectionExtensions.cs
- src/SAIF.NCore.Messaging/Options/MessagingOptions.cs
- src/SAIF.NCore.Messaging/Options/OutboxOptions.cs
- src/SAIF.NCore.Messaging/Options/ConfigureMessagingOptions.cs
- src/SAIF.NCore.Messaging/Hosting/OutboxDispatchService.cs
- src/SAIF.NCore.Messaging/Outbox/SqlOutboxStore.cs
- src/SAIF.NCore.Messaging/SAIF.NCore.Messaging.csproj
````
