# Technical documentation — unityNodejsApi

Evidence date: 2026-09-30. Revision: `master` `8d9588c` (2019-12-01).

Credential values are omitted. Host name, database name, MySQL user, column names, and the Lambda function name below are taken from source.

## What this repository is

A Bitbucket Git repository of a Node.js AWS Lambda entrypoint and a MySQL login module. Bitbucket Pipelines zips the tree and updates Lambda function `unityAuth` in `us-east-2`.

There is one branch, `master`. Five commits, from 2019-11-11 through 2019-12-01. 505 tracked files. 500 of those are under `node_modules/`.

Author of every commit: `siliconoverdrive` (`jaco@overdrive.co.za`).

`sonar-project.properties` and `sonarqube_scan.bat` were listed by the onboarding scan and are not in git history.

## Repository layout

```text
unitynodejsapi/
  index.js                  Lambda exports.handler
  login.js                  loginUser, verify, getAccessToken
  test.js                   Script. Runs on load. Not required by index.js
  bitbucket-pipelines.yml   Zip and aws-lambda-deploy update
  package-lock.json         npm lockfileVersion 1. No package.json
  node_modules/             Vendored dependencies, 500 files
```

No README, `package.json`, `.gitignore`, `.sql`, Dockerfile, SAM/CloudFormation template, or test directory.

`node_modules` is tracked. Git will keep those files even if a later ignore rule were added. There is no ignore rule in this repository.

## Runtime

Pipeline image: `node:10.15.3` (`bitbucket-pipelines.yml`). The first commit used `nodejs:10.x` for a few minutes (`bd7d5af`, subject "update image").

The Lambda runtime, architecture, memory, timeout, VPC, and handler string are not in git. `index.js` exports `handler`, which matches the usual `index.handler` setting. **Unknown / Requires Confirmation** that the function is configured that way.

`exports.handler` is an `async` function of one argument, `event`. It is not the Node 8 callback signature `(event, context, callback)`. The removed authorizer in `login.js` was that callback signature.

Module scope holds `var result = ""`. A warm Lambda container keeps Node module state. Each successful arm overwrites `result`. **Inferred** from the `var` placement. This repository has no reuse test.

## Handler contract

Input fields the code reads:

| Field | Used when | Code |
|---|---|---|
| `module` | Always | `switch (event.module)`. Only `"auth"` is a case |
| `action` | `module` is `"auth"` | `login`, `verify`, `access-token` |
| `email`, `password` | action `login` | Passed into `loginUser` |
| `token` | action `verify` | Passed into `verify`, which ignores it |
| `access_token` | action `access-token` | Passed into `getAccessToken` |

Output when the function returns:

```text
{ statusCode: 200, body: JSON.stringify(result) }
```

`result` is:

- login: `[200, { email: "Check your username/email", password: "Check your password" }]`
- verify: `undefined`, and `JSON.stringify(undefined)` is `undefined`
- access-token: `[401, { error: "Invalid access token detected" }]`
- auth with no matching action: `""`, so the body is the JSON string `""`

Any other `module` throws `ReferenceError` on `context` before a response object is built.

The query callback in `loginUser` can throw `ReferenceError: passwordin is not defined` after the handler has returned. Which of those two outcomes a Lambda invocation records is **Unknown / Requires Confirmation**.

## Login module

`login.js` exports three functions. It does not export a handler at HEAD. It did, from `e367364` until `d4602f7`.

### Connection

`mysql.createPool` from package `mysql2` 2.0.1:

- host `unityqa.csigt2kcstpl.us-east-2.rds.amazonaws.com`
- user `dbadmin`
- database `unityqa`
- password: literal in `login.js` and `test.js`, omitted

A new pool is created on every `loginUser` call. `getConnection` ignores its error. `connection.release()` runs at the start of the query callback, before `throw` on query error. The pool is never `end()`ed.

From `d4602f7` to `21214d8` the driver was `mysql` 2.17.1 `createConnection`, with `connection.end()` after `query` was scheduled. That package is still in `node_modules` at HEAD. Nothing at HEAD requires it.

### Query

```sql
SELECT strUuid as uuid,
       strUsername as email,
       strPassword as passwordq,
       strRole as role,
       txtPreference as data
FROM users
WHERE strUsername = <escaped email>
  AND strPassword = <escaped md5 hex>
```

The statement is one string. `mysql.escape` is interpolated into it. There is no second-argument placeholder array.

MD5 is `crypto.createHash('md5')` from Node's `crypto`, not from the npm package `crypto` 1.0.1 that is also in the lockfile. Node core module names win over `node_modules` of the same name. **Inferred** that the npm `crypto` package is unused by this `require`.

### JWT

Library: `jsonwebtoken` 8.5.1, vendored.

`jwtConfig` exists only inside `loginUser`:

- `secret`: literal, omitted
- `expiresIn`: `"2 days"`

Sign payload: `{ id: user.uuid }`. No `algorithm` option, so the library default applies (HS256 for a string secret in jsonwebtoken 8.x). The algorithm is not named in this repository. **Inferred** from the library default, not from a local option.

`getAccessToken` calls `jwt.verify(access_token, jwtConfig.secret)` but `jwtConfig` is not in scope, so execution enters `catch`.

### `test.js`

Same pool, same query, same JWT config as `login.js`, copied rather than required. It sets `passwordin` in that file, so the hash line can run. Loading the file opens the pool immediately. There is no `module.exports` and no assertion library.

Do not execute it against a live database to "check the docs." It contains a real-looking username and password and it writes a query to RDS.

## Dependencies

`package-lock.json` is lockfileVersion 1 and starts with `"requires": true`. There is no `package.json` in any commit, so the direct-dependency list is not declared. Packages named by `require` or by a commit:

| Package | Lockfile version | Role |
|---|---|---|
| `jsonwebtoken` | 8.5.1 | Sign and verify. Present from the first commit's `node_modules` |
| `mysql2` | 2.0.1 | Driver at HEAD. Added in `8d9588c` |
| `mysql` | 2.17.1 | Driver from `d4602f7` through `21214d8`. Still vendored |
| `crypto` (npm) | 1.0.1 | In the lockfile. Application uses Node core `crypto` |
| `jwks-rsa` | not present | Required by `login.js` before `d4602f7` only |

The rest of `node_modules` (cardinal, esprima, iconv-lite, and others) is the transitive tree those installs pulled in, plus whatever else was installed without a manifest. **Unknown / Requires Confirmation** which extra top-level packages were intentional. The pipeline never runs npm, so the vendored tree is the deploy artifact.

## Deployment

`bitbucket-pipelines.yml`, default pipeline, two steps:

1. **Build and package.** `apt-get install zip`, `zip -r codeNodejs.zip *`, artifact `codeNodejs.zip`.
2. **Update Lambda code.** `atlassian/aws-lambda-deploy:0.2.1` with `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` from pipeline variables, `AWS_DEFAULT_REGION` `us-east-2`, `FUNCTION_NAME` `unityAuth`, `COMMAND` `update`, `ZIP_FILE` `codeNodejs.zip`.

No caches, no deployment environment, no branch-specific pipeline, no manual trigger block. Bitbucket runs the default pipeline on branches that do not match another pipeline. Only `master` exists here.

The pipe updates code. It does not set the handler, environment, or aliases. Those settings, if any, live in AWS. **Unknown / Requires Confirmation.**

## Security

Recorded so a reviewer can find them. Values are not repeated.

- RDS password literal in `login.js` and `test.js` since `d4602f7`.
- JWT HMAC secret literal in `login.js` (`21214d8` onward) and `test.js`.
- A username and password literal in `test.js` (`8d9588c`).
- MD5 for the password digest (`21214d8` onward).
- `21214d8` built SQL by concatenating email and digest. HEAD uses `mysql.escape`.
- `getAccessToken` at `21214d8` referenced `_` and `authDB`, which were not imported. That is not an authentication check.
- The handler does not authenticate the Lambda caller (BR-001 in `business-rules.md`).
- Pipeline AWS keys are variable references, not literals.

If the RDS user or the JWT secret is still in use, they have been in git since 2019 and should be rotated. That is a review note, not a behaviour the code implements.

## Logging

`login.js` and `test.js` `console.log` the inner error email, the user row, `user.passwordq`, and the `{ user, access_token }` object. The user row includes the password digest alias. **Implemented.** There is no log library and no redaction.

## Development and testing

No test script, linter, formatter, or CI test step.

`test.js` is a one-shot script. Running it is a live database call, not a unit test.

Local Node version is not pinned outside the pipeline image. No `.nvmrc`.

## Monitoring

No metrics, alarms, X-Ray, or health check are configured in this repository. Lambda and RDS monitoring would be in AWS. **Unknown / Requires Confirmation.**

## History of `login.js`

| Revision | File behaviour |
|---|---|
| `e367364`, `bd7d5af` | API Gateway authorizer. `jwks-rsa`, RS256, Bearer token, IAM Allow. Own `exports.handler`. Package `jwks-rsa` not vendored |
| `d4602f7` | `mysql` connection. `SELECT * from users`. Empty `func2`. `index.js` calls `loginUser` for action `login` |
| `21214d8` | MD5, concatenated SQL, JWT sign, `verify`, `getAccessToken`. `index.js` requires `module == 'auth'` |
| `8d9588c` | `mysql2` pool, `mysql.escape`, column list with `strUuid` and `strRole`. `index.js` uses `switch`. `test.js` added |

`index.js` and `login.js` are the whole application. Behavioural changes belong in those two files plus `test.js` and the pipeline image line.
