# Project plan — paymyfines-backend-new

Evidence date: 2026-10-08.

Source repository: `git@bitbucket.org:overdrive/paymyfines-backend-new.git`.

Inspected revision: `main` at `c01bc83` (2025-02-27, Jaco Brits, "deploy new"). Full hash `c01bc83810ee8dd035870baba60e871e96066d86`. That commit is `origin/HEAD`. The only remote branch is `main`. There are no tags.

The scan-host path named on the onboarding issue (`~/projects/sonar_scan/repos/paymyfines-backend-new`) was not on this machine. The tree below was read from the git revision above. That revision matches the commit the issue records (`c01bc83`, 2025-02-27 19:41:36 +0200).

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

There was no prior Silicon Ark directory for `paymyfines-backend-new`.

## Product

**Documented in code and mail copy, not in a product brief.** Cognito custom-message subjects are "Pay My Fines: Sign Up", "Pay My Fines: Resent code", and "Pay My Fines: Forgot Password" (`Functions/External/Cognito/GenerateCustomeMail.cs`). The support address constant is `help@paymyfines.co.za` (`classes/Constants.cs`).

**Inferred from behaviour.** The API lets a caller look up traffic infringements from two upstream systems (iForce and eNatis), record an iVeri Lite card payment, email a receipt, and later push the paid amount to the source system. It also stores user profiles, settings, API logs, finance rows, and dashboard graph definitions in MySQL.

`README.md` does not describe Pay My Fines. It is the Silicon Overdrive `serverlessDotNetStarter` guide (hello-world Lambda, .NET Core 3.1, `us-east-1`). That guide disagrees with the deployed shape in `serverless.yml` and `AwsDotnetCsharp.csproj`.

Related Silicon Ark directories that already exist, and are not named by this repository:

- `paymyfines-frontend-new`
- `paymyfines-frontend`
- `paymyfines-pdf-application`
- `paymyfines-worker`
- `Paymyfines-CronJob`
- `pmf-backend-ah`
- `pmf-frontend-ah`

Whether this API is the backend those frontends call is **Unknown / Requires Confirmation**. Path names in this `serverless.yml` (`/getfinesearch`, `/getpaginatedfines`, `/user/details`, `/iveripayment`) match routes described in the `paymyfines-frontend-new` PRD. That match is corroboration, not a link committed in this repo.

## Objectives (inferred from the implementation, not from a written plan)

- Expose HTTP Lambdas, in AWS `eu-west-1`, that search and pay infringements.
- Keep a local MySQL record of users, payments, and whether a notice was already paid here, so the caller can block a second payment.
- Settle successful iVeri payments with iForce and eNatis on a schedule.
- Send Pay My Fines branded Cognito mail from templates stored in MySQL.
- Provide finance and graph data for an operator UI. This API does not check a role before returning that data.

## Scope

In scope, because it is committed:

- Serverless Framework service `tmt-pmf` (development) and `tmt-pmf-prod` (production).
- 29 Lambda handler classes under `Functions/`.
- MySQL access through AWS Secrets Manager secret `pmf-rds`.
- Calls to one base URL from secret `pmf-enatis`, used for both iForce and eNatis paths.
- iVeri Lite return handling, receipt HTML, and a PDF microservice (`pmf-pdf-server`) plus an invoice bucket (`pmf-invoices-bucket`).
- Amazon SES SMTP (`pmf-ses-smtp`) and a from-address secret (`pmf-mail`).
- A Cognito Custom Message trigger on an existing user pool.
- A scheduled settlement job and an unauthenticated HTTP trigger for the same job.
- Bitbucket Pipelines SonarQube scan on `main`.
- Sample API Gateway event JSON under `TestRequests/`.

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

- The public website, Cognito hosted UI, and iVeri hosted payment page.
- The iForce and eNatis systems themselves. Only the HTTP paths this code calls are visible.
- The MySQL schema (no migrations or DDL). Table and column names are visible only where SQL strings name them.
- Infrastructure as code for the VPC, RDS instance, Cognito pool, or secrets. `developmentVpcConfig.yml` and `productionVpcConfig.yml` only list security group and subnet IDs to attach at deploy time.
- Automated deployment. The pipeline does not build or deploy.

## System architecture

```text
Caller (browser or other HTTP client)
  -> API Gateway HTTP APIs (CORS *, no authorizer in serverless.yml)
  -> .NET 6 Lambda (one function per route)
       -> MySQL (secret pmf-rds)
       -> AWS Secrets Manager (eu-west-1)
       -> upstream base URL (secret pmf-enatis)
            -> IForce/* and infringement/*
       -> Google reCAPTCHA siteverify
       -> SES SMTP (email-smtp.eu-west-1.amazonaws.com)
       -> PDF HTTP service (secret pmf-pdf-server)
       -> S3 invoice bucket (secret pmf-invoices-bucket; upload method is commented out)

Cognito user pool (existing)
  -> Custom Message trigger -> GenerateCustomEmail Lambda -> MySQL setting templates

EventBridge schedule rate(2 hours), name RunCronJobDev
  -> RunCronJob Lambda -> same settlement calls as the HTTP route GET /runcronjob
```

Lambdas run inside the VPC subnets and security group for the selected stage.

## Major components

| Area | Where | Role |
|---|---|---|
| HTTP functions | `Functions/External`, `Functions/Internal` | API Gateway handlers |
| Settlement job | `Functions/Jobs/RunCronJob.cs`, `Services/PaymentService.cs` | Push paid notices to iForce and eNatis |
| Shared runtime | `classes/PmfBase.cs` (`Pmfbase`) | Opens MySQL and loads the upstream base URL |
| Validation | `classes/Helper.cs`, `Model/APIModel.cs` | Required fields and format checks |
| HTTP envelope | `Services/ResponseService.cs` (`HttpService`) | `{ result, payload }` plus CORS `*` |
| Secrets | `Services/SecretsManagerService.cs` | RDS, SES, upstream URL, PDF host, bucket, mail-from |
| Receipts | `Services/PaymentReceiptService.cs` | HTML receipt, PDF POST, SES mail |
| Graphs | `Services/GraphService.cs` | Runs SQL stored in the `graph` table |
| Deploy | `serverless.yml`, `build.cmd`, `build.sh` | Package `pay-my-fines-lambda.zip` and deploy |

## Milestones

| When | Evidence |
|---|---|
| 2025-02-27 | `671ef26` adds `.gitignore` only |
| 2025-02-27 | `77b887d` and `6ce8e08` add and edit `bitbucket-pipelines.yml` online in Bitbucket |
| 2025-02-27 | `53020f9` adds `sonar-project.properties` online in Bitbucket |
| 2025-02-27 | `c01bc83` "deploy new" adds the application. Author `Jaco Brits <jaco@netstart.co.za>` |

Nothing in git is dated after 2025-02-27. No milestone document, version tag, or changelog is in the tree.

## Implementation plan

No implementation plan is committed. The README "Silicon sequence" is a starter checklist (`dotnet add package MySql.Data`, edit `Handler.cs`, deploy with profile `pmf`, curl a `us-east-1` hello URL). `Handler.cs` is not in this tree. The package reference in the project file is `MySqlConnector`, not `MySql.Data`.

What the tree shows as the build path:

1. `build.cmd` or `build.sh`: `dotnet restore`, then `dotnet lambda package` for `net6.0` into `bin/release/net6.0/pay-my-fines-lambda.zip`.
2. `serverless deploy`, with an example in the README of `--stage development --aws-profile pmf-dev`.

## Known dependencies

Runtime packages in `AwsDotnetCsharp.csproj`:

- `Amazon.Lambda.APIGatewayEvents` 2.4.0
- `Amazon.Lambda.Core` 1.2.0
- `Amazon.Lambda.Serialization.Json` 1.8.0
- `Amazon.Lambda.AspNetCoreServer` 5.3.0 (referenced; no ASP.NET host is in the tree)
- `AWSSDK.S3` 3.5.1
- `MySqlConnector` 2.2.7
- `Newtonsoft.Json` 12.0.3
- `Amazon.Extensions.CognitoAuthentication` 2.0.3
- `AWSSDK.CognitoIdentityProvider` 3.5.1.17
- `AWSSDK.SecretsManager` 3.5.0

`Select.HtmlToPdf.NetCore` is commented out. Receipts are built as HTML and posted to an external PDF URL.

`yarn.lock` is committed. There is no `package.json`. Serverless Framework is an external CLI, not a committed Node dependency.

External systems the code calls are listed in `technical-documentation.md`.

## Current project status

**Implemented** as a single snapshot on `main`. The pipeline on `main` runs SonarQube only (`bitbucket-pipelines.yml`). It does not compile, test, or deploy.

**Unknown / Requires Confirmation:**

- Whether `main` at `c01bc83` is what is running in development or production.
- Whether the maintenance message documented for `paymyfines-frontend-new` means this API is also withdrawn from public use.
- Ownership of the upstream iForce/eNatis host, the PDF service, and the MySQL schema.
- Whether `terminalId = 0` on iForce settlement (`Services/PaymentService.cs`, comment "what goes here??") is accepted by iForce.
