Skip to content

Example: Configuration

The configuration document records how a console application is configured across environments: the settings it retrieves from the Environment API, the DatabaseConfig registrations that produce its connection strings, the App.config surface, and the log destinations. Doc gen produces one per application at docs/applications/<app-slug>/configuration.md.

What reviewers should check

  • The page states that connection strings are resolved from the Environment API through each DatabaseConfig's environment config key rather than stored in <connectionStrings>, and the App.config section that follows does not contradict it with a literal connection string.
  • Every Environment API row names the retrieval method (GetConfigSetting or GetSecureConfigSetting) and the consuming class, and Secure is Yes for every value retrieved securely.
  • The database configuration table's Config name values match the Autofac registration names used to resolve IUnitOfWork, and each row's environment config key is the key the instance name is resolved from.
  • App.config subsections with no entries are omitted rather than left empty; ApplicationHost appears in appSettings because the Environment API host is resolved from it.
  • The log destination table maps file0-file4 to what this application actually writes, marking unused ids "Not used" instead of inventing content.
  • The environment variance table contains only verified values and uses Unknown rather than a guess; a row repeated identically across DEV, TEST, and PROD should be checked against the environment data, not assumed.
  • Inherited framework statements carry † so a reviewer can tell application behaviour from framework behaviour.

Example

The document below is a complete, correct console-configuration.md for a fictional .NET Framework console application.

View rendered example — the same document as a real page, so you can compare rendering as well as source.

---
title: Configuration
summary: Environment API settings, database configurations, and app.config surface.
status: draft
owner: Policy Systems Team
last_reviewed: 2026-09-10
---

# Configuration

`SAIF.Policy.RenewalNotice` carries almost no configuration of its own. The
`App.config` deployed with the executable names the Environment API host, the
Oracle managed driver, and the log4net appender; everything that varies by
environment — the database instance behind `policyDb`, the Agency API base
address and key, the notice window, the print vendor drop path, and the summary
mail recipients — is retrieved at run time from the Environment API for the track
the executable is running on. The same binaries therefore run in DEV, TEST, and
PROD without a config transform.

Configuration is retrieved at runtime from the Environment API through `IEnvironmentService`.
Connection strings are **not** stored in `<connectionStrings>`; they are resolved from the database instance name returned for each `DatabaseConfig`'s environment config key.†

## Environment API settings

| Key | Retrieved by | Consuming class | Secure | Varies by environment | Purpose |
| --- | --- | --- | --- | --- | --- |
| `policy.db.instance` | `GetConfigSetting` | `Program` | No | Yes | Oracle instance name behind the `policyDb` `DatabaseConfig` registration. |
| `policy.db.password` | `GetSecureConfigSetting` | `Program` | Yes | Yes | Password for the `POLICY_APP` database user used by the `policyDb` unit of work. |
| `agency.api.baseUrl` | `GetConfigSetting` | `RenewalNoticeApplication` | No | Yes | Base address of `SAIF.Agency.Api`, used to construct the `SAIF.Agency.Api.Client` agency client. |
| `agency.api.apiKey` | `GetSecureConfigSetting` | `RenewalNoticeApplication` | Yes | Yes | API key sent by the agency client on every agency and agent request. |
| `renewalnotice.noticeWindowDays` | `GetConfigSetting` | `NoticeGenerator` | No | No | Default lead time in days applied to the notice window when the notice template does not override it. |
| `renewalnotice.printQueuePath` | `GetConfigSetting` | `NoticeQueueWriter` | No | Yes | UNC path of the print vendor drop folder that generated notice documents are written to. |
| `renewalnotice.notificationRecipients` | `GetConfigSetting` | `RenewalNoticeApplication` | No | Yes | Semicolon-separated addresses for the run summary mail sent by `Finish`. |
| `renewalnotice.healthProbeAgencyNumber` | `GetConfigSetting` | `RenewalNoticeApplication` | No | No | Agency number used for the Agency API health probe in `Initialize`. |

## Database configurations

Each entry is a `DatabaseConfig` passed to `RegisterCommonDependencies` in `RegisterAppDependencies`. `Config name` is the Autofac registration name used to resolve the corresponding `IUnitOfWork`.

| Config name | Type | Environment config key | Database user | Stateless | Server | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `policyDb` | `OracleConfig` | `policy.db.instance` | `POLICY_APP` | No | Resolved per track from the Environment API | Reads `POLICY.POLICY_TERM` and `POLICY.NOTICE_TEMPLATE`, and writes `POLICY.RENEWAL_NOTICE` and `POLICY.RENEWAL_NOTICE_QUEUE` through the NHibernate unit of work. |

## app.config settings

### appSettings

| Key | Value | Read by | Purpose |
| --- | --- | --- | --- |
| `ApplicationHost` | `https://environmentapi.example.saif` | `EnvironmentServiceBase` | Environment API host resolution† |
| `ApplicationName` | `SAIF.Policy.RenewalNotice` | `ProgramRunnerBase` | Identifies the application to the Environment API and appears in the header, footer, and summary mail. |
| `AgencyApiTimeoutSeconds` | `30` | `RenewalNoticeApplication` | Request timeout applied to the agency client; a term whose agent lookup exceeds it is skipped and logged to `file2`. |
| `PrintFileExtension` | `.afp` | `NoticeQueueWriter` | Extension of the generated print document expected by the print vendor pickup job. |

### Custom configuration sections

| Section | Purpose |
| --- | --- |
| `oracle.manageddataaccess.client` | Oracle managed driver configuration |
| `hibernate-configuration` | NHibernate dialect (`Oracle10gDialect`), driver, and batch size used by the session factory built from the `policyDb` config |
| `log4net` | Rolling file appender for the application log that sits alongside the `file0`-`file2` destinations |

### Assembly binding redirects

| Assembly | Redirected to | Note |
| --- | --- | --- |
| Newtonsoft.Json | 13.0.0.0 | Aligns the version pulled in by `SAIF.Web.API.Clients` with the one the agency client contracts are compiled against |
| Oracle.ManagedDataAccess | 4.122.21.1 | Pins the managed driver version that `SAIF.Framework.Data.NHibernate` was built against |
| System.Runtime.CompilerServices.Unsafe | 6.0.0.0 | Required by the HTTP stack used underneath `SAIF.Web.API.Clients` |

## Log file destinations

Log outputs are resolved from **machine-level environment variables** `file0`–`file4`, scanned by `ConsoleLogService` at construction. Each variable's value is a log file path.†

| Environment variable | Log id | Content written by this application |
| --- | --- | --- |
| `file0` | `LogType.File0` | Run control log: header block, resolved arguments, notice window, per-100-notice progress lines, totals, and fatal errors |
| `file1` | `LogType.File1` | Notice detail: one line per generated notice with policy number, renewal effective date, agency number, servicing agent, and delivery channel; dry-run lines carry a `WHATIF` marker |
| `file2` | `LogType.File2` | Exception detail: one line per skipped or failed term with policy number, agency number, and the exception message |
| `file3` | `LogType.File3` | Not used |
| `file4` | `LogType.File4` | Not used |

## Environment variance

| Setting | DEV | TEST | PROD | Notes |
| --- | --- | --- | --- | --- |
| `policy.db.instance` | `POLICYDEV` | `POLICYTST` | `POLICYPRD` | Same `POLICY_APP` user in all three; only the instance differs. |
| `agency.api.baseUrl` | `https://agencyapi-dev.example.saif/` | `https://agencyapi-test.example.saif/` | `https://agencyapi.example.saif/` | DEV and TEST point at the corresponding `SAIF.Agency.Api` deployments. |
| `renewalnotice.noticeWindowDays` | `45` | `45` | `45` | Same in all tracks; the `NonRenewal` template overrides it with the statutory 60 days. |
| `renewalnotice.printQueuePath` | `\\printdev\drop\renewalnotice` | `\\printtest\drop\renewalnotice` | `\\printprd\drop\renewalnotice` | The DEV and TEST shares are drained by a cleanup job rather than by the print vendor. |
| `renewalnotice.notificationRecipients` | `policysystems-dev@example.saif` | `policysystems-test@example.saif` | `batchops@example.saif;policysystems-oncall@example.saif` | Only PROD notifies operations. |
| `agency.api.apiKey` | Unknown | Unknown | Unknown | Retrieved with `GetSecureConfigSetting`; values are not readable from the environment data. |

## Related documentation
- [Application index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Run lifecycle](run-lifecycle.md)
- [Arguments](arguments.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Data model](data-model.md)
- [Operational runbook](operational-runbook.md)
- [Tech debt](tech-debt.md)

## Sources
- `src/SAIF.Policy.RenewalNotice/App.config`
- `src/SAIF.Policy.RenewalNotice/Program.cs`
- `src/SAIF.Policy.RenewalNotice/RenewalNoticeApplication.cs`
- `src/SAIF.Policy.RenewalNotice/NoticeQueueWriter.cs`
- `deploy/environment-settings/renewalnotice.settings.json`