# Project plan — pmf-backend-ah

Evidence date: 2026-10-06.

Source repository: `git@bitbucket.org:overdrive/pmf-backend-ah.git`.

Inspected revision: `master` at `064c4fa` (2022-05-06, Jaco Brits, "Afterhandover gitcommit"). The scan-host path `~/projects/sonar_scan/repos/pmf-backend-ah` was not on this machine. The tree below was read from that git revision. Secret values (database password, SMTP password, reCAPTCHA secret) are not copied here. Sample JSON under `TestRequests/` contains personal identifiers; those values are omitted.

This plan describes what the repository contains. It does not decide what the product should become.

There is no product requirements document in the source repository and no prior Silicon Ark set for `pmf-backend-ah`. `README.md` is the upstream Serverless .NET Core starter (`serverlessDotNetStarter`), plus a short "Silicon sequence" at the bottom. Where the README disagrees with `serverless.yml` and `Handler.cs`, the code is the implemented behaviour and the README is stale starter text.

## Product

**Inferred** from the service name `tmt-pmf-prod`, the deployment artifact `pay-my-fines-lambda.zip`, receipt copy "Payment Receipt", and the addresses `payment@paymyfines.co.za` and `help@paymyfines.co.za`.

What the code does is an AWS Lambda API, written in C# on .NET Core 3.1, that:

- stores Pay My Fines users, identity numbers, transactions, infringements, charges, settings, graphs, and API logs in MySQL;
- looks up traffic fines at an internal HTTP API that fronts iForce and eNaTIS;
- records an iVeri Lite card payment and emails a PDF receipt;
- retries settlement of those payments to iForce and eNaTIS on a schedule;
- serves finance and dashboard graph data.

**Documented** in `serverless.yml` header comments as Silicon Overdrive, with support `helpdesk@overdrive.co.za`. The Cognito pool name, mail host, and failure-mail recipient use TMT naming (`tmt-pmf-prod-user-pool`, `noreply@paymyfines.co.za`, `csenekal@office.tmtservices.co.za`).

**Unknown / Requires Confirmation:** the current product owner, whether TMT Services operates the product, and whether this API is still deployed.

## Branch reality

| Line | Tip | Date | What it is |
|---|---|---|---|
| `master` (default; `origin/HEAD`) | `064c4fa` | 2022-05-06 | Only branch. Two commits, both on 2022-05-06 |

Nothing in git is dated after 2022-05-06. Whether the API is still deployed is **Unknown / Requires Confirmation**.

| Commit | Date | Author | Subject |
|---|---|---|---|
| `0c97000` | 2022-05-06 07:19 UTC | Jaco Brits (`jaco@overdrive.co.za`) | Initial commit (empty of application source; the handover commit adds the tree) |
| `064c4fa` | 2022-05-06 09:24 +0200 | Jaco Brits (`jaco@netstart.co.za`) | Afterhandover gitcommit — adds the application, Serverless template, tests samples, and Sonar scanner output |

The generated Sonar working directory recorded in `.sonarqube/out/sonar-project.properties` is `C:\wamp64\www\PMF\pmf-backend`, project key `TMTBackend`. That path is not this Bitbucket slug. **Inferred:** this repository is a handover snapshot of a project that lived locally as `pmf-backend`.

## Scope in this repository

In scope, because it is implemented here:

- HTTP API on API Gateway, stage `production`, region `eu-west-1`, AWS profile `pmf-prod`.
- Cognito User Pool custom-message trigger (pool `tmt-pmf-prod-user-pool`, `existing: true` — the pool is not created by this template).
- MySQL access through credentials in AWS Secrets Manager.
- Scheduled settlement job, also exposed as `GET /runcronjob`.
- PDF receipt generation via an internal HTML-to-PDF service, then S3 bucket `tmt-pmf-prod-invoices`, then SES SMTP email.

Out of scope, because it is not in this repository:

- The web or mobile client. A logo URL points at an Amplify app host (`master.d39rr3ejryd4rk.amplifyapp.com`). That app is not in this repo.
- The iForce and eNaTIS systems themselves. This service calls an internal HTTP gateway at `http://10.106.3.22:80/api/`.
- iVeri Lite hosted payment pages. This service stores the iVeri reference and handles the return redirect. It does not contain the card form.
- Infrastructure-as-code beyond `serverless.yml` (no Terraform, no pipeline file).

## Architecture

```text
Caller (browser or app; not in this repo)
    |  HTTPS, CORS enabled, no API authorizer in the template
    v
API Gateway  eu-west-1  stage production  service tmt-pmf-prod
    |
    v
One Lambda package (pay-my-fines-lambda.zip), many handlers in Handler.cs
    |-- MySQL (RDS secret pmf-prod-rds)  users, fines, payments, settings, graphs, logs
    |-- Cognito User Pool tmt-pmf-prod-user-pool  CustomMessage trigger only
    |-- Google reCAPTCHA siteverify
    |-- Internal API 10.106.3.22  iForce and eNaTIS query/pay
    |-- EventBridge schedule  rate(2 hours)  settlement cron
    |-- HTML-to-PDF 10.106.3.158:8080
    |-- S3 tmt-pmf-prod-invoices
    `-- SES SMTP (secret pmf-prod-ses-smtp)  receipts and failed-settlement mail
```

The Lambda runs in a VPC (`sg-0ef1507ae1fcd0913`, subnets `subnet-0c1aaf57b8d9fdb93` and `subnet-0827171db5e6ea7bb`). **Inferred:** that VPC is how the function reaches the private `10.106.3.0` addresses. Confirmation of the network design is required.

## Major components

| Component | Where | Role |
|---|---|---|
| HTTP and Cognito handlers | `Handler.cs` (`PMF.Handler`) | All deployed entry points |
| Request validation | `classes/Helper.cs`, `Model/APIModel.cs` | Required fields and a few format checks |
| Response envelope | `Services/ResponseService.cs` (`HttpService`) | `{ result, payload }` plus CORS header |
| Secrets | `Services/SecretsManager.cs` | RDS and SES SMTP secrets |
| Settlement | `Services/PaymentService.cs` | Posts paid infringements to iForce and eNaTIS |
| Double-pay guard | `Services/PaymentChecker.cs` | Reads `infringement.intPaid` |
| Receipt | `Services/PaymentReceiptService.cs` | HTML, PDF service, S3, email |
| Graphs | `Services/GraphService.cs` | Runs SQL stored in the `graph` table |
| Failure mail | `Services/MailService.cs` | Cron mail when settlement keeps failing |
| Constants | `classes/Constants.cs` | Region, mail, internal URLs, reCAPTCHA secret |
| Deploy | `serverless.yml`, `build.cmd`, `build.sh` | Package and CloudFormation via Serverless |

## Milestones visible in git

There is no project plan, changelog, or milestone list in the repository. The only history is the empty initial commit and the same-day handover commit. Earlier product history, if any, is **Unknown**.

## Implementation plan (as left in the repo)

The README "Silicon sequence" and `build.cmd` describe the build the author used:

1. `dotnet restore` and `dotnet lambda package` to `bin/release/netcoreapp3.1/pay-my-fines-lambda.zip`.
2. `serverless deploy --aws-profile pmf` in the README sequence. `serverless.yml` and `aws-lambda-tools.default.json` name the profile `pmf-prod`.
3. The README sequence curls a different API (`4row8qyxh1`, `us-east-1`, `/dev/hello`). That URL is the starter example. The header of `serverless.yml` lists `https://puru95wxc8.execute-api.eu-west-1.amazonaws.com/production/...`.

There is no Bitbucket Pipelines file, no test project, and no migration scripts. Schema lives only as SQL strings inside the handlers.

## Known dependencies

- .NET Core 3.1, Amazon Lambda tools, Serverless Framework, Node.js (for the Serverless CLI only; `yarn.lock` is four lines and is not an application lockfile).
- NuGet: API Gateway events, Lambda core, MySql.Data 8.0.23, Newtonsoft.Json 12.0.3, Cognito Identity Provider, Secrets Manager, S3.
- AWS: API Gateway, Lambda, Cognito (existing pool), Secrets Manager, S3, SES SMTP, EventBridge schedule, VPC.
- External: Google reCAPTCHA, iForce, eNaTIS (via the internal API), iVeri Lite (return payload), an HTML-to-PDF service.

## Current project status

**Implemented** as a single handover snapshot on `master`. Last change 2022-05-06.

**Unknown / Requires Confirmation:**

- Whether `https://puru95wxc8.execute-api.eu-west-1.amazonaws.com/production` is still the live API.
- Whether the schedule `rate(2 hours)` named `RunCronJobDev` was left in a test cadence. Comments in `serverless.yml` also say every 8 hours and "2 hours for testing".
- The task-creation file list included `sonar-project.properties` and `sonarqube_scan.bat` at the repo root. Those files are not in `origin/master`. `sonar-scanner.bat` and the generated `.sonarqube/` and `.scannerwork/` trees are in git.
- Which client repository calls this API.
