Skip to content

Example: .NET console app dependencies

Doc gen writes docs/applications/<app-slug>/dependencies.md once per console application to record the libraries, packages, APIs, and databases a run depends on. Reviewers cross-check it against the project file, packages.config, and RegisterAppDependencies, because a wrong Reference Type changes how the portal links the application to the libraries it consumes.

What reviewers should check

  • SAIF.Framework.Windows appears in Internal dependencies as a NuGet Package with no project path. Recording it as a Project Reference is a defect even when the surrounding description is right.
  • Reference Type is exactly one of Project Reference, NuGet Package, or NuGet Package (same-repo); values such as "Framework" or "Shared" are wrong.
  • Sections appear in template order — Internal, External, Transitive, API, Database connections, Dependency risks and notes, Related documentation, Sources — and a conditional section with no rows is omitted entirely rather than filled with "None".
  • Transitive rows exclude BCL and System.* packages, name the source framework by its canonical dotted library name rather than a folder slug, and carry †. The framework types reached through SAIF.Framework.Windows belong here, not in the internal table.
  • The API dependencies table names concrete endpoints, the class that calls them, and the config key the base URL comes from, and those endpoints match the client package's documented surface.
  • Database connections list one row per DatabaseConfig registered in RegisterAppDependencies, with the config name matching the Autofac registration name used to resolve IUnitOfWork.
  • Every dependency table ends with a Usage column that says how this application uses the dependency, not what the package does in general.

Example

The document below is a complete, correct console-dependencies.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: Dependencies
summary: Internal libraries, external packages, framework components, API endpoints, and database connections.
status: draft
owner: Policy Systems Team
last_reviewed: 2026-09-10
---

# Dependencies

`SAIF.Policy.RenewalNotice` has a small, entirely package-based dependency
surface: there are no project references in the repository. It takes two
internal NuGet packages — `SAIF.Framework.Windows` for the console lifecycle and
`SAIF.Agency.Api.Client` for agency and agent lookups — and picks up the rest of
the SAIF framework transitively through them. Externally it depends on the Oracle
managed driver, NHibernate, Autofac, and the usual JSON and logging packages. All
persistence is against a single Oracle database registered as `policyDb`, and the
only outbound HTTP calls are to `SAIF.Agency.Api`.

## Internal dependencies

| Dependency | Reference Type | Project path | Usage |
| --- | --- | --- | --- |
| `SAIF.Framework.Windows` | NuGet Package | — | Console application framework: runner, argument container, and lifecycle base classes |
| `SAIF.Agency.Api.Client` | NuGet Package | — | Supplies `AgencyClient`/`IAgencyClient`; `GetAgency` and `GetAgentsForAgency` resolve the agency and appointed servicing agent printed on each notice. |

## External dependencies

| Dependency | Version | Usage |
| --- | --- | --- |
| Oracle.ManagedDataAccess | 21.11.0 | Managed Oracle driver behind the `policyDb` NHibernate session factory. |
| NHibernate | 5.3.13 | Maps `PolicyTerm`, `RenewalNotice`, `RenewalNoticeQueueItem`, and `NoticeTemplate`, and provides the unit of work the notice transaction commits through. |
| Autofac | 6.5.0 | Container built in `RegisterAppDependencies`; resolves `RenewalNoticeApplication` and its services. |
| Newtonsoft.Json | 13.0.3 | Serializes the agency and agent payloads exchanged with `SAIF.Agency.Api` and the notice merge model handed to the template renderer. |
| log4net | 2.0.15 | Writes the application log configured in `App.config` alongside the `file0`-`file2` destinations. |
| System.Configuration | 4.0.0.0 | Reads `ApplicationHost`, `ApplicationName`, `AgencyApiTimeoutSeconds`, and `PrintFileExtension` from `App.config`. |
| System.Net.Mail | 4.0.0.0 | Sends the run summary mail from `Finish` to `renewalnotice.notificationRecipients`. |

## Transitive dependencies

Dependencies in this section are inherited from framework packages — for a console application on `SAIF.Framework.Windows` this includes `SAIF.Framework.Common`, `SAIF.Framework.Data.NHibernate`, `SAIF.HashUtil`, and `SAIF.Web.API.Clients`. They are not directly referenced by this application but are required at runtime.

| Dependency | Source framework | Type | Usage |
| --- | --- | --- | --- |
| `IConsoleLogService` | `SAIF.Framework.Common` | Transitive | Console and file logging surface injected into `ConsoleBase`† |
| `IUnitOfWork` | `SAIF.Framework.Data.NHibernate` | Transitive | NHibernate unit of work resolved from the container† |
| `IEnvironmentService` | `SAIF.Framework.Core` | Transitive | Environment API configuration retrieval† |
| `SaifConsoleException` | `SAIF.Framework.Windows` | Transitive | Exception hierarchy that maps `DatabaseErrorException`, `DataErrorException`, `FileInputOutputException`, and `NoDataFoundException` to exit codes 2, 3, 4, and 6.† |
| `SaifStandardCommandLineParser` | `SAIF.Framework.Windows` | Transitive | Parses the named arguments and echoes each resolved value before `Initialize` runs.† |
| `SAIF.HashUtil` | `SAIF.Framework.Common` | Transitive | Produces the notice document hash stored on `POLICY.RENEWAL_NOTICE` so a regenerated notice can be compared to the queued one.† |
| `JsonHttpClient` | `SAIF.Web.API.Clients` | Transitive | HTTP surface underneath `AgencyClient`: request composition, the API key header, timeout enforcement, and the result envelope.† |

## API dependencies

| Endpoint | Method | Called from | Base URL config key | Usage |
| --- | --- | --- | --- | --- |
| `v1/agencies/{agencyNumber}` | GET | `AgentResolver` (`GetAgency`) | `agency.api.baseUrl` | Resolves the agency name and mailing address printed in the notice footer, and serves as the `Initialize` health probe for the agency number in `renewalnotice.healthProbeAgencyNumber`. |
| `v1/agencies/{agencyNumber}/agents` | GET | `AgentResolver` (`GetAgentsForAgency`) | `agency.api.baseUrl` | Returns the agents appointed at the agency; the appointed servicing agent for the policy term is selected from this list and printed as the contact. |

## Database connections

| Database | Config name | Schema/User | Access method | Usage |
| --- | --- | --- | --- | --- |
| Policy (Oracle) | `policyDb` | `POLICY` schema, `POLICY_APP` user | NHibernate `IUnitOfWork` | Reads eligible terms from `POLICY.POLICY_TERM` and the template from `POLICY.NOTICE_TEMPLATE`; inserts `POLICY.RENEWAL_NOTICE` and `POLICY.RENEWAL_NOTICE_QUEUE` rows in the per-notice transaction. |

## Dependency risks and notes
- `SAIF.Framework.Windows` is consumed as a NuGet package, so the argument
  parser, the exit-code mapping, and the header and footer output change only
  when the package version is bumped and the application is redeployed. The exit
  codes the operational runbook documents come from that package, not from
  `Program.cs`.
- `SAIF.Agency.Api.Client` 3.2.0 is compiled against the `v1` routes of
  `SAIF.Agency.Api`. A breaking change on the API side surfaces here as skipped
  notices rather than a failed run, because agent resolution failures are
  per-term recoverable errors — the failure count in the run summary is the only
  signal.
- The agency client is constructed once in `Initialize` and reused for the whole
  batch. A mid-run outage of `SAIF.Agency.Api` therefore skips every remaining
  term instead of failing fast, which is why the summary mail lists affected
  policy numbers.
- `Oracle.ManagedDataAccess` 21.11.0 is pinned by a binding redirect to match the
  version `SAIF.Framework.Data.NHibernate` was built against. Upgrading it for
  this application alone reintroduces the redirect conflict.
- `Newtonsoft.Json` 13.0.3 arrives both directly and transitively through
  `SAIF.Web.API.Clients`; the redirect in `App.config` is what keeps the two
  consistent at run time.
- The application has no project references, so nothing in this repository can be
  changed in a way that affects a run without a package version change. That
  makes deployments predictable but means a fix in the agency client requires a
  package release rather than a rebuild.

## Related documentation
- [Application index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Run lifecycle](run-lifecycle.md)
- [Arguments](arguments.md)
- [Configuration](configuration.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/SAIF.Policy.RenewalNotice.csproj`
- `src/SAIF.Policy.RenewalNotice/packages.config`
- `src/SAIF.Policy.RenewalNotice/App.config`
- `src/SAIF.Policy.RenewalNotice/Program.cs`
- `src/SAIF.Policy.RenewalNotice/AgentResolver.cs`
- `src/SAIF.Policy.RenewalNotice/Mappings/RenewalNoticeMap.cs`