# Project plan — nodehtmltopdf

Evidence date: 2026-10-08.

Source repository: `git@bitbucket.org:overdrive/nodehtmltopdf.git`.

Inspected revision: `master` at `dc92bed` (2022-02-09, Jaco Brits, "revert previous changes"). That commit is `origin/HEAD`. The only remote branch is `master`. There are no tags.

The scan-host path named on the onboarding issue (`~/projects/sonar_scan/repos/nodehtmltopdf`) was not on this machine. The tree below was read from a clone of the git revision above. That revision matches the commit the issue records (`dc92bed`, 2022-02-09 23:07:35 +0200).

AWS key material in `cred.json` is omitted. The file is tracked. See `technical-documentation.md`.

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

## Product

**Documented** in `README.md` (added in `24d9561`, 2022-02-09): a Node.js microservice, written by Silicon Overdrive, that generates PDF documents from HTML. The introduction says it was created because Lambda struggled to generate PDFs. A caller posts JSON to the server on port 8080 and receives JSON with a filename and a path.

**Implemented** in `index.js`: an Express process listens on port 8080. `POST /htmltopdf` renders `req.body.html` with `html-pdf` and uploads the file to S3 bucket `tmt-pmf-prod-invoices` in `eu-west-1`. The HTTP response is sent before that upload finishes.

The npm package name is `htmlpdfapi`. The listen log says `HTML2PDF`. `GET /` logs `PMF PDF Generator`. The README title is `PDF Generator`. The git slug is `nodehtmltopdf`.

**Inferred** from those names, the bucket `tmt-pmf-prod-invoices`, and Silicon Ark's `pmf-backend-ah` documents: this process is a candidate for the Pay My Fines receipt PDF service. `pmf-backend-ah` posts `{ "html": ... }` to `http://10.106.3.158:8080/htmltopdf` and then reads `filename` from S3 bucket `tmt-pmf-prod-invoices`. This repository does not contain that IP, and it does not name `pmf-backend-ah`. The match is path, port, bucket, region, and the `filename` field. It is not proof that this revision is what listens on that address.

`paymyfines-pdf-application` is an empty remote (a `.gitignore` only). Its Silicon Ark set already says it is not evidence of a PDF server. This repository does not name it.

**Unknown / Requires Confirmation:** whether anything still runs this process, on which host, and which caller posts to it.

## Branch reality

| Line | Tip | Date | What it is |
|---|---|---|---|
| `master` (default; `origin/HEAD`) | `dc92bed` | 2022-02-09 | Only branch. 18 commits, 2021-10-04 through 2022-02-09 |

No other local or remote branches were present at inspection. Nothing in git is dated after 2022-02-09.

Authors: Jaco Brits. `d71c3c7`, `9025de3`, `cd53ca0`, and `4ae97fd` use `jaco@overdrive.co.za`. The other fourteen commits use `jaco@netstart.co.za`.

## Objectives

No objectives file exists. What the commits actually did:

1. `d71c3c7` (2021-10-04) — Bitbucket initial commit. `.gitignore` only.
2. `9025de3` (2021-10-04, "First commit") — Express app in `server.js` on port 3000, `html-pdf`, S3 upload to `pmf-invoices`. The PDF body is the literal `<b>hello world</b>`.
3. `b1b1f63` — rename `server.js` to `index.js`.
4. `fed7c50` ("PDF Content app") — upload the file bytes and set `contentType` to `application/pdf`. The HTML source is still the hello-world literal.
5. `22e7404` ("update defualt text") — PDF body becomes `req.body.html`.
6. `eacf1df` ("update latest code") — port 8080, bucket and response URL `pmf-development-invoices`, listen log `HTML2PDF`. Dependency lockfile grows sharply.
7. `3e07698` ("update web accessable pdf") — `ACL: 'public-read'` on the upload.
8. `b62094a` ("update acl to private") — that ACL line is commented out.
9. `c575fc2` ("Update new master - prod deployment") — response URL host becomes `tmt-pmf-prod-invoices`. The upload `Bucket` at that commit is still `pmf-development-invoices`.
10. `4ae97fd` and `cd53ca0` (Bitbucket online edits) — upload bucket and `config.js` `bucket` become `tmt-pmf-prod-invoices`.
11. `24d9561` through `8b0e7b5` — README, `SecretsManager.js`, and an attempt to load secret `pmf-prod-s3-user` instead of `cred.json`. `cred.json` is deleted in `24d9561`.
12. `dc92bed` ("revert previous changes") — `index.js` again loads `./cred.json` and uploads to the hardcoded bucket `tmt-pmf-prod-invoices`. The secrets-manager variant is saved as `index_wit SM.js`. `cred.json` is restored.

## Scope

### In scope of `master` at `dc92bed`

Tracked files:

| Path | Role |
|---|---|
| `index.js` | Process entry. `package.json` `main` and `start` |
| `index_wit SM.js` | Alternate entry saved by the revert. Not referenced by `package.json` |
| `SecretsManager.js` | AWS Secrets Manager `getSecret`. Required by both entry files. Called only from `index_wit SM.js` |
| `config.js` | Bucket name and a `hewer` logger. Required by `index.js`. Neither export is read |
| `cred.json` | AWS `accessKeyId`, `secretAccessKey`, `region`. Values omitted |
| `package.json` | Package `htmlpdfapi` 1.0.0 |
| `package-lock.json` | npm lockfileVersion 1 |
| `README.md` | The only product document in the source repo |
| `.gitignore` | Ignores `node_modules/` and `dist/`. Also a stock list of Java, Python, Maven, and media patterns |

Nine tracked files. `node_modules/` is not tracked.

### Out of scope / not in this repository

- `sonar-project.properties` and `sonarqube_scan.bat`. The onboarding scan listed them beside the git files. They are not in git history.
- Dockerfile, Bitbucket Pipelines, Serverless or CloudFormation template, PM2 ecosystem file, test directory, and an `engines` field.
- The EC2 instance, security groups, S3 bucket policy, and IAM user. The README names Amazon Linux 2, S3, and Lambda. None of those resources are defined here.
- The caller. No client source is in this repo.

## System shape

```text
HTTP caller (unknown in this repo)
  → Express on port 8080  (index.js; README says post to the server IP)
       GET /                 echo request body; log "PMF PDF Generator"
       POST /pdf             echo request body
       POST /htmltopdf       html-pdf (PhantomJS) → local .pdf file
                             → S3 tmt-pmf-prod-invoices (eu-west-1)
                             → JSON { filename, path } sent before the upload callback
  credentials: cred.json via AWS.config.loadFromPath
```

`index_wit SM.js` is the same HTTP shape, with credentials loaded from Secrets Manager secret `pmf-prod-s3-user` inside `app.listen`. It is not the `npm start` entry.

## Major components

| Component | Role | Evidence |
|---|---|---|
| `index.js` | HTTP server and the running entry | **Implemented**. Started by `npm start` and named by README as the file to run, except the install section says `pm2 start index.html` |
| `html-pdf` | Render HTML to a PDF file | **Implemented** call `pdf.create(html, options).toFile` |
| S3 upload | `AWS.S3.upload` to `tmt-pmf-prod-invoices` | **Implemented** in the file callback |
| `cred.json` | Static AWS keys for the running entry | **Implemented**. Keys omitted |
| `SecretsManager.js` + `index_wit SM.js` | Alternate credential load | **Implemented** as files. Not the start script after `dc92bed` |
| `config.js` | Declares the same bucket name and a logger | **Implemented** module. Unused by the request handlers |
| README install | Amazon Linux 2, Node 16, PM2, a system PhantomJS binary | **Documented**. Not a script in the repo |

## Milestones

The only milestones are the commits in [Objectives](#objectives). There is no roadmap file. The last commit reverts the secrets-manager entry rather than finishing it.

## Dependencies known from the tree

Direct `require` calls in `index.js`: `express`, `body-parser`, `cors`, `html-pdf`, `fs`, `aws-sdk`, `./SecretsManager.js`, `./config.js`.

`config.js` requires `hewer`.

Lockfile versions at `dc92bed`: `express` 4.17.1, `html-pdf` 3.0.1, `aws-sdk` 2.1072.0, `cors` 2.8.5, `body-parser` 1.19.0, `hewer` 0.4.0, `phantomjs-prebuilt` 2.1.4, `phantomjs` 2.1.7, `wkhtmltopdf` 0.4.0, `pm2` 5.1.2, `memorystream` 0.3.1.

`wkhtmltopdf` and `memorystream` are not required by any application file. `phantomjs` and `phantomjs-prebuilt` are not required directly. `html-pdf` is the package that launches PhantomJS. The README also installs a separate PhantomJS 2.1.1 Linux binary and symlinks it to `/usr/bin/phantomjs`. The `phantomPath` option in `index.js` is commented out.

README install uses NodeSource `setup_16.x`. `package.json` has no `engines` field.

## Current status

The repository stopped on 2022-02-09. The running entry is the `cred.json` path, not Secrets Manager. `POST /htmltopdf` answers with a filename and an S3 URL before the PDF file exists, and it does not report render or upload failure to the client. `pagesize` is read and then ignored. Page format is the literal `Letter`.

**Unknown / Requires Confirmation:**

- Whether an EC2 instance still runs `index.js` or PM2, and whether that host is `10.106.3.158` (the address recorded in Silicon Ark for `pmf-backend-ah`, not in this repo).
- Whether `pmf-backend-ah` or `paymyfines-backend-new` (secret `pmf-pdf-server`) is a current caller.
- Whether bucket `tmt-pmf-prod-invoices` still exists, and whether objects are readable without authentication. The public-read ACL was removed in `b62094a`.
- Whether the AWS keys in `cred.json`, and older keys in git history (`16d9273`, `b781463`), are still valid. They should be treated as exposed. This document does not copy them.
- Whether secret `pmf-prod-s3-user` exists and was ever used in production.
- Why the scan host had `sonar-project.properties` and `sonarqube_scan.bat` when git does not.
- Whether `https://github.com/TMTServices/pmf-pdfgeneration.git` (the clone URL in the README) is a former copy of this code.
- Whether CloudWatch is configured on the host. The README says logs go there. The code only calls `console.log`.
