Files
2026-03-11 11:18:25 -05:00
..
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00
2026-03-11 11:18:25 -05:00

Introduction

TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.

Getting Started

TODO: Guide users through getting your code up and running on their own system. In this section you can talk about:

  1. Installation process
  2. Software dependencies
  3. Latest releases
  4. API references

Build and Test

TODO: Describe and show how to build your code and run the tests.

Contribute

TODO: Explain how other users and developers can contribute to make your code better.

If you want to learn more about creating good readme files then refer the following guidelines. You can also seek inspiration from the below readme files:

Landmark Online Loan Application Backend

The Landmark OLA backend provides a RESTful API facade over the CRIF ACTion SOAP API. The backend is built to abstract away the vendor sepcific calls and could be adapted to use alternative loan application / decisioning vendors.

This project targets .NET 8.0. Unit tests are built with xUnit.

Swagger OpenAPI documentation is generated by Swashbuckle.AspNetCore and is available at /swagger.

Suggested IDE

Visual Studio 2017 Community Edition

Logging

.NET has 7 logging levels:

Name Level
Trace 0
Debug 1
Information 2
Warning 3
Error 4
Critical 5
None 6

Information levels logs will contain URLs requested by the client, which could contain Loan Application IDs and may (but should not) contain PII.

Logging is set to Debug for the Development environment and to Error for the Production environment via the appsettings.ENVIRONMENT.json files. CRIF ACTion API calls are logged by a WCF behavior (CRIF.ACTion.Communication.WcfInspector) at the Debug level. Logs can be enabled in Azure using the filesystem Application Logging feature. Note that this feature will turn off after 12 hours to prevent any acceidental logging of PII.

Contributing style/naming conventions

  • All private fields in a class should be prefixed with an underscore (_) and camel case. Ex: private VendorConfiguration _vendorConfiguration
  • All public fields in a class should be PascalCase. Ex: public Task<string> SendMessageToCrif(){...}
  • All local variables should be camelCase. Ex: var formatString = "This string is formatted"

Adding new endpoints and vendor calls

  1. Update/create models in Landmark.OLA.Models.
  • As the amount of models grow over time these may require additional organization.
  • Use System.ComponentModel.DataAnnotations attributes to set data validation for the controller. Note that display attributes may not apply since this project is not using MVC views.
  1. Update IVendorClient and implementations with any new methods or parameters.
  2. Create required objects in the CRIF.ACTion project.
  • 'ApiCalls' represent individual API calls made to CRIF, and should extend the ApiCall class.
  • Other objects, such as MainSections or AppDetails classes can be created to represent XML sections or elements. The IBuildable interface offers a common way to return XElement content.
  • Store product IDs, custom field IDs, and other CRIF data in CrifConstants.cs.
  1. Update/create required controllers in the Controllers directory of Landmark.OLA.Application.
  • Controllers should inherit OlaControllerBase and have an [ApiController] attribute at the class level.
  • Controllers should have a constructor that accepts IVendorClient vendorClient, ILogger<*ClassName*> logger parameters. These items will be injected by .Net Core's Service Configuration, as set in Startup.cs's ConfigureServices method.
  • Controller methods should:
    • be async
    • return Task<IActionResult>
    • log exceptions without logging PII, but return consumer-friendly errors
    • contain no vendor-specific code
    • have ProducesResponseType attributes, per Swashbuckle's Explicit Responses instructions
      • [ProducesResponseType(typeof(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary), 400)] for validation errors (checked automatically by ASP.NET 2.1)
      • [ProducesResponseType(500)] for uncaught exceptions, if applicable
    • Call [FluentValidation](https://fluentvalidation.net/) for business-level model validation.
  1. Create additional LoanType enum values as required.
  • Loan limits, purposes, and term lengths may need to be updated with new types. The SettingsCheck tests will verify that all types either have values or are explicitly excluded.
  1. Create or update tests as required.

Validation

Field level validation is handled on the model level with the System.ComponentModel.DataAnnotations attributes. It's important to consider the default value of types and how this may impact validation. For example, bool defaults to false, so if you do not want to assume false on a null value instead of bool use Nullable / bool?.

Variable length value-type fields (that is, strings or decimals but not Guids or enums) should generally have length or range validation. These validation limits may be derived from CRIF's database field definitions or perhaps by business logic. Validation requirements are checked on all classes in Landmark.OLA.Models via reflection by the VerifyDataAnnotations() unit test.

Business level validation, such as checking a valid HMDA state, is handled with the [FluentValidation](https://fluentvalidation.net/) library which should be called within the controllers.

Areas To Enhance

  1. Add additional test coverage for the CRIF API. *A soapui test suite exists in the landmark folder. The suite must be ran manually and the results have to be analyzed upon completion. *At some point we want to create an automated test suite that is ran everytime we build the api. The results should be automatically analyzed. This will allow us to monitor any behavior changes on CRIFS end.
  2. Add run time validation on CRIFS response xml. CRIF currently validates all request xml. *See xml validation in unit tests to get started
  3. Hide status/build info controller in production *Prevents external entites from checking prod server status *Can use env.IsProduction() check for validating environment. Inject environment object into controller.
  4. Establish a way to identify when CRIF is down
  5. Add error handling and reporting when CRIF is down
  6. Add automated testing for custom CRIF Fields *CRIF has custom fields for specific loan types. *If we submit a loan to CRIF with an invalid custom field, the submission is rejected. *If we submit a loan to CRIF with a disabled field, the submission is accepted but nobody will be able to view it in CRIF. (Big Risk) *We should setup regular automated tests to validate that the custom fields still exist AND are enabled. API function exists to check fields.
  7. Modify the IIS App Pool Settings for faster site loading *Currently the back-end takes some extra time to load if IIS has taken it out of memory due to lack of activity. Likely can remove time-outs and either remove recycling or change to always overnight. *https://weblogs.asp.net/owscott/why-is-the-iis-default-app-pool-recycle-set-to-1740-minutes

Running in Docker

Use the provided Dockerfile to build and run the API in a container.

# Build the image from the repository root
docker build -t loanwizard-api .

# Run the container and expose the HTTP port
docker run --rm -p 8080:8080 \
  -e ASPNETCORE_ENVIRONMENT=Development \
  -e Vault=<key-vault-name> \
  -e ClientId=<service-principal-client-id> \
  -e ClientSecret=<service-principal-secret> \
  loanwizard-api

The application binds to port 8080 inside the container. Override configuration and secrets by providing environment variables (for example Primary__SeqUrl, ApplicationStorage__Host, etc.). When using Azure Key Vault, ensure that Vault, ClientId, and ClientSecret correspond to a principal that has access to the configured vault. If you do not need Key Vault integration for local testing, set ASPNETCORE_ENVIRONMENT=Development and provide configuration values directly through environment variables or JSON files mounted into the container.

##Azure Active Directory Security

We are using v1.0 (ADAL).

To secure additional endpoints you only need to include an annotation in the controller: [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] Either on the entire controller, or on an endpoint by endpoint basis

Resources: https://docs.microsoft.com/en-us/azure/active-directory/develop/index https://docs.microsoft.com/en-us/azure/active-directory/develop/web-api https://docs.microsoft.com/en-us/azure/active-directory/develop/web-app https://docs.microsoft.com/en-us/azure/active-directory/develop/azure-ad-endpoint-comparison

##Cosmos DB Time To Live Index (TTL) The time to live index is used to automatically expire loans in the db based on an expiration time in seconds. TTL goes off of the last modified time.

Steps for setting up TTL

  1. Download a mongodb client. Recommendation is Robo 3T (Robomongo).
  2. Connect to the db using the client.
  3. Open the shell and run the following command: db.ApplicationsDvl.createIndex({"_ts":1}, {expireAfterSeconds: 14400}) *db.ApplicationsDvl denotes the database and collection *createIndex({"_ts":1} indicates an index is being applied to the _ts field *{expireAfterSeconds: 14400} indicates to expire the document after 14400 seconds (4 hours)
  4. Verify the index was created by viewing the index section.

Notes

  1. When connecting using a client, make sure the ssl authentication method is self-signed cert.
  2. Robo 3T will delete the index when you edit it in the ui. Always use the shell.
  3. _ts is a Cosmos DB-specific field and is not accessible from MongoDB clients. It is a reserved (system) property that contains the timestamp of the document's last modification.
  4. The azure portal also has a built in TTL setting. We are not relying on this for TTL management.

Resources https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-robomongo https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-indexing https://docs.microsoft.com/en-us/azure/cosmos-db/time-to-live https://docs.microsoft.com/en-us/azure/cosmos-db/how-to-time-to-live