# Features — findndrive_api_net

Evidence date: 2026-10-15. Source: `git@bitbucket.org:overdrive/findndrive_api_net.git`, `master` at `a2414dd` (2023-12-12).

Status words: **Current** means present and wired on `master`. **Completed** is not used separately, because this remote has no release tags and no "done" checklist. **Planned** means only an inline comment or README sentence with no implementation. Nothing in the tree is marked deprecated.

Git history after the 2023-11-15 import is a pipeline file and a README edit. Feature-level history before that import is not in this remote. Migration names are the only earlier timeline.

## Current features

### F-01 — Pre-qualification estimate

**Status:** Current.

`POST /api/Financing/Pre-Qualification` stores an applicant and returns monthly and total financing amounts.

Evidence: `FindAndDrive.API/Controllers/FinancingController.cs` (`Financing`), `FindAndDrive.Domain/Services/FinancingService.cs` (`FinancingCalc`, `getMonthlyandTotalAmounts`).

Swagger includes this action. It requires the `Financing` permission.

### F-02 — Bureau prediction

**Status:** Current.

`POST /api/Financing/Prediction` calls Experian and TransUnion, writes finance, credit, fraud alert, audit log, and prediction, and returns the applicant id.

Evidence: `FinancingController.Analytics`, `FinancingService.Analytics`, `ExperianGateway`, `TransUnionGateway`.

A second call for the same applicant id returns HTTP 409.

### F-03 — Applicant read-back

**Status:** Current.

`GET /api/Financing/GetApplicantById` returns the subset of stored fields described in the PRD (WF-5).

Evidence: `FinancingController.GetApplicantById`, `FinancingService.GetApplicantById`, `ApplicantRepository.Get`.

### F-04 — Hidden direct bureau proxies

**Status:** Current. Hidden from Swagger.

`POST /api/Financing/Experian` and `POST /api/Financing/Transunion` return the raw bureau payload. The TransUnion proxy requests fraud and credit. The prediction feature requests credit only.

Evidence: `FinancingController` actions `Experian` and `TransUnion`, both `[ApiExplorerSettings(IgnoreApi = true)]`.

### F-05 — API-key JWT login and refresh

**Status:** Current.

`POST /api/Authentication/token` is anonymous. `POST /api/Authentication/refresh` requires a bearer token.

Evidence: `AuthenticationController`, `AuthenticationService`, `ApiKeyHelper` (32 random bytes, base64, with `/`, `+`, and `=` removed; SHA-256 hex hash).

### F-06 — Client directory

**Status:** Current. Hidden from Swagger.

Create, list active, get by id, rename. No deactivate and no delete.

Evidence: `ClientController`, `ClientService`.

### F-07 — API key lifecycle

**Status:** Current. Hidden from Swagger.

Create (plaintext secret returned once), list, revoke, reinstate.

Evidence: `ApiKeyController`, `ApiKeyService`, `ApiKeyMapper` (list DTO omits the hash).

### F-08 — Role list

**Status:** Current. Hidden from Swagger.

`GET /api/Role` returns seeded roles. There is no create-role or edit-role route. Startup overwrites permissions of existing role names from `SeedData` on every boot.

Evidence: `RoleController`, `SeedData`, `Startup.ApplyMigration`.

### F-09 — Permission policies

**Status:** Current.

Policies named `Client`, `ApiKey`, `Role`, and `Financing` require a matching `Permissions` claim.

Evidence: `FindAndDrive.Domain/Models/DTO/Permissions.cs`, `Startup.ConfigureServices`.

Seeded assignment:

| Role | Permissions |
|---|---|
| `SystemAdmin` | `Client`, `ApiKey`, `Role` |
| `Financing` | `Financing` |

### F-10 — Startup migration, role sync, and bootstrap admin

**Status:** Current.

Evidence: `Startup.ApplyMigration`, `Startup.CreateInitialClient`.

### F-11 — Swagger UI

**Status:** Current.

Always on. Bearer security scheme. XML comments from the API and Domain assemblies. Decimal types mapped for OpenAPI.

Evidence: `Startup` `AddSwaggerGen` and `UseSwagger` / `UseSwaggerUI`.

### F-12 — Structured API errors

**Status:** Current.

400, 409, and 504 for the three domain exception types. Other exceptions become a generic 500.

Evidence: `FindAndDrive.API/Middleware/ExceptionMiddleware.cs`.

### F-13 — SQL Server persistence

**Status:** Current.

Tables from the EF model: `Clients`, `Roles`, `ApiKeys`, `Applicants`, `ApplicantFinance`, `ApplicantCredit`, `ApplicantFraudAlert`, `ApplicantAuditLog`, `ApplicantPredicition` (spelling as in the code).

Evidence: `DefaultContext`, `DefaultContextModelSnapshot`.

Latest migration: `20230525092856_Kappa`.

### F-14 — SQL Server backup in the repo

**Status:** Current as a file. Contents not verified.

`database/FindAndDrive.bak`, about 5.0 MB. README says it is the initial database and already has admin credentials.

### F-15 — Unit tests for the estimate, the predictor, and API keys

**Status:** Current as source. They were not executed in this documentation pass.

Evidence:

- `FindAndDrive.Tests/UnitTests/Services/FinancingServiceTests.cs` — two `FinancingCalc` facts and six `MakePrediciton` scenarios.
- `FindAndDrive.Tests/UnitTests/Services/ApiKeyServiceTests.cs`
- `FindAndDrive.Tests/UnitTests/Helpers/ApiKeyHelperTests.cs`

Several financing facts disagree with the current formulas. See `business-rules.md`. That disagreement is a documentation conflict, not a separate product feature.

### F-16 — Integration tests against a real host startup

**Status:** Current as source. Not executed here.

`FinancingControllerTests` and `ClientControllerTests` use `WebApplicationFactory<Startup>` with no database override, so they use whatever `DefaultConnection` the test process has. `FinancingControllerTests` seeds a client, a `Financing` key, and an applicant, then calls pre-qualification and prediction.

Evidence: `FindAndDrive.Tests/IntegrationTests`.

### F-17 — NBomber performance harness

**Status:** Current as source. Not part of CI.

`FindAndDrive.Tests.Performance` targets `https://localhost:5001`.

- Admin scenario: 10 iterations per second for 30 seconds. Creates a client, reads it, lists roles, creates a `Financing` key, lists keys.
- Financing "normal": ramp of 1 every 3 seconds for 30 seconds through pre-qualification, prediction, and get-by-id.
- Financing "stress": 10 every 3 seconds for 30 seconds through the same three calls.

The harness contains hardcoded API key ids and secrets. Values are omitted. Provenance: **Implemented**. Whether those keys still exist anywhere is **Unknown**.

### F-18 — SonarQube on master

**Status:** Current.

`bitbucket-pipelines.yml` installs OpenJDK 17 and `dotnet-sonarscanner`, then `dotnet build` between scanner begin and end. No test command. Branch filter `{master}`.

`sonarqube_scan.bat` and `sonar-project.properties` are not in the commit. The onboarding issue listed them at discovery time. Provenance of that listing versus git: **Requires Confirmation** (they are absent at `a2414dd`).

## Planned or only commented

| Item | Evidence | Status |
|---|---|---|
| Turn JWT issuer, audience, and `SaveToken` on for production | Comments in `Startup` JWT setup | Planned only as comments. Not implemented |
| Dedicated error when the applicant id does not exist | Comment in `FinancingService.Analytics` | Not implemented |
| Source of `RiskBankDescription` | Comment in `Analytics`; value stored as empty string | Unknown |
| Whether `EstimatedApprovalAmount` is monthly or yearly | Comment on that assignment | Unknown |
| GitHub duplicate with GitHub Actions | Last line of `README.md` | Not in this tree. URL unknown |

## Recently changed

On this remote, the only changes after the 2023-11-15 `First commit` are:

| Date | Commit | Change |
|---|---|---|
| 2023-11-15 | `d8d781d` | Added `bitbucket-pipelines.yml` |
| 2023-12-12 | `a2414dd` | README edited in Bitbucket |

Schema changes inside the imported tree, by migration name (February to May 2023):

- `InitialMigration`, `EntityConfigurations`
- `AddedApplicantEntities`, `addClientForeignKey`, `AddedMaxLengthToEnums`
- `PreMergeIntoDeev`, `AddedNullableModifiedAt`
- `AddedMonthlyAndTotalCosts`, `FindAndDriveId`
- `ChancesOfApprovalEnum`, `AddingCorrectTypes`
- `reasonVerbiageLongerLength`, `AddedAuditLogToApplicantAuditLog`
- `IncreasedLengthOfChancesOfApproval`, `ReasonVerbiageLengthChange`
- `UpdatedGenderMSForApplicant`, `Kappa`

What each migration altered beyond its name was not diffed line by line. The names are the evidence used here.

## Removed or deprecated

No feature flag, obsolete attribute, or commit message in this remote's four commits removes a feature.

`Gender`, `MaritalStatus`, and `Province` enums exist under `FindAndDrive.Domain/Models/Enums`. `Applicant` stores those three fields as strings. The configuration comment says "Configure Enum Mapping" and then calls `HasConversion<string>()` on the string properties. The enums are not the column types. Provenance: **Implemented**. Whether an earlier model used the enums is **Unknown** (`UpdatedGenderMSForApplicant` only shows that gender and marital status were altered in May 2023).

## Not features of this repository

- Vehicle catalogue, staff screens, and session steps. Those appear in Silicon Ark under `findndrive_webportal`. This API does not reference that project.
- A public progressive web app. `findndrive_pwa` is a separate Silicon Ark directory. This API does not reference it.
