# Technical documentation — myPass-App

Evidence date: 2026-10-09. Inspected revision: `master` at `d8d04bf` (2022-06-22). Remote: `git@bitbucket.org:overdrive/mypass-app.git`.

## Summary

Static mobile web app. HTML fragments are fetched into one shell. Product calls go to `https://footprintapp.net/api/mypass/`. Hosting described in-repo is S3 plus CloudFront, driven by Bitbucket Pipelines. There is no server-side application in this repository.

## Stack

| Area | What is in the tree |
|---|---|
| UI | HTML, CSS, JavaScript. No framework bundler, no `package.json`. |
| Theme | Bootstrap-based Enabled mobile theme in `styles/` and `scripts/bootstrap.min.js`. Font Awesome under `fonts/`. Inter from Google Fonts. |
| PWA | `_manifest.json` version `1.0`, display `standalone`, orientation `portrait`, `start_url` `index.html`. |
| HTTP | `fetch` in `requestAPI`. |
| QR | `plugins/qr-scanner-master` (camera) and `plugins/EasyQRCodeJS` (draw the pass QR). |
| PDF | `plugins/pdfjs` for certificate preview. |
| Images | Cropme is included under `plugins/cropme` and used by `editImage` on the registration flow. |
| PHP | `php/contact.php` only. Not called by the shell. |
| Tests | None. No PHPUnit, Jest, or CI test step. |
| Sonar | `sonar-scanner.bat` launches SonarScanner CLI 4.6.2 from `C:\sonar-scanner`. Not referenced by `bitbucket-pipelines.yml`. |

`index.html` loads, in order: `scripts/app.js`, `scripts/bootstrap.min.js`, EasyQRCodeJS, PDF.js and its worker, qr-scanner UMD and legacy builds, `scripts/custom.js`, `scripts/core.js`, `scripts/core2.js`. Paths are root-absolute (`/scripts/...`).

`scripts/core_old.js` and `scripts/core_epic.js` are earlier copies. They are not loaded.

## Application structure

```text
index.html                 shell, footer, menus, script tags
sign_in_sign_up.html       separate document for sign-in (sets page = sign_in_sign_up)
Onboard.html               separate document for the carousel
*.html content pages       fragments fetched by loadPage
scripts/core.js            session, API helper, home, pass, profile, registration, navigation
scripts/core2.js           symptom check, certificates, QR scanner, PDF preview
scripts/custom.js          theme, service-worker registration, PWA prompt (Enabled theme)
_service-worker.js         cache Cache-v3.06
_manifest.json
menu-main.html             side menu fragment
php/contact.php            unused mail boilerplate
domains_old.js             unused host → event id map
docs/*.pdf                 protocol PDF, not loaded by the app
exports/                   design HTML, not the running shell
plugins/                   vendored QR, PDF, crop, charts, lightbox
scss/                      theme sources
styles/                    compiled CSS
```

`loadPage(page)` fetches `page + '.html'`, writes it into `#page-content`, pushes `?page=&params=`, stops a live QR scanner, and fires `pageHasLoaded`. `popstate` on `/` or `/index.html` loads the page from the query string.

`pageHasLoaded` dispatches: `registration_form`, `home_screen`, `my_pass`, `screen_history`, `screen_result`, `screen_result_review`, `myprofile_edit`, `myprofile_view`, any `symptom_step_*`, `health_certificates`, `add_health_certificate`.

`DOMContentLoaded` calls `login_and_auth` when `page == "sign_in_sign_up"` and `onboard_screens` when `page == "onboard"`.

## Runtime data

Session and UI keys in `localStorage` (prefix `MyPass` unless noted):

| Key | Writer |
|---|---|
| `MyPass-LoggedInUserData` | `getlogin` data array, or `blankPerson` |
| `MyPass-AMID` | password verify, removed after `postpwd` |
| `MyPass-HomeNextEventID` | first event `AC` on home |
| `MyPass-AccreditationStatus` | written on home, never read |
| `MyPass-nextEventID` | `doSymptomCheck` |
| `MyPass-symptomScreening` | symptom wizard |
| `MyPass-eventID`, `MyPass-eventData`, `MyPass-screeningID` | symptom and result screens |
| `MyPass-external` | `"true"` on the logged-out symptom deep link |
| `MyPass-AfterLoginRedirect` | query string saved when a deep link needs sign-in |
| `MyPass-Highlight` | forced to `orange` in several places |
| `MyPass-Theme`, gradient, PWA prompt keys | `scripts/custom.js` |

`LoggedInUserData[0]` fields the UI reads include `AMID`, `Ref`, `FirstName`, `Surname`, `IDNumber`, `Mobile`, `MobileNumberPre`, `Email`, `Gender`, `City`, `StateProvince`, `Country`, `Address1`, `Address2`, `Nationality`, `PostalCode`, `DateOfBirth`, `User_pic_base64`, `FirstLogin`.

There is no database schema in this repository. Shapes above are the client contract.

## API client

`requestAPI(request, parameters, type="POST")` in `scripts/core.js`:

- Host is `https://footprintapp.net/api/mypass/` + `request`.
- If `debug` is true, the host is `https://qa.footprintapp.net/api/mypass/`. `debug` is `false`.
- POST sends `JSON.stringify(parameters)` unless `parameters` is `FormData`.
- GET appends query parameters and sends no body. Call sites in this revision use the default POST, including path-style URLs such as `geteventsperuser/MemberReference/{ref}` and `getevent/EventID/{id}`.
- `mode` is `cors`. No `Authorization` header and no credentials mode.
- Non-OK responses throw `Error` with the status. The caller usually `console.log`s or toasts.

`registerSymptomUser` duplicates the accreditation POST with its own `fetch` instead of `requestAPI`.

The action list and expected fields are in `prd.md` (Integrations).

## Auth

Sign-in and password update send plaintext passwords in the JSON body. No hashing step exists on `master`. Branch `encryption` (`1fc083c`, not merged) is titled "md5 hashing on password".

`userAutoLogin` sends a fixed password string that is hard-coded in `scripts/core.js`. It is used only for URL-driven symptom and review entry. The value is visible to anyone who can read the shipped script.

`getfirstlogin` is commented out. Session persistence is `localStorage` only. `logout` clears the whole store.

## Event ids in this revision

| Value | Where it is applied |
|---|---|
| `304` | `staticEventID` for `registration_form` → `getevent` and `postaccreditation` |
| `345` | `userAutoLogin` screening payload `eventID` and `AC`; `registerSymptomUser` accreditation `eventID` |
| `346` | `indexLoad` when forcing `symptom_step_1` or `screen_result_review`; fallback when a deep link omits `eventID` |

`domains_old.js` is a map (`bil2021` → `304`, `bil2021media` → `325`, `cts` → `331`, `eap` → `329`, `fnb` → `332`, `loftus` → `330`, `local` and `9hour` → `346`, `sarugby` → `209`, `rc` → `341`). Nothing loads it. **Inferred** leftover from before the registration form was split into `mypass-registration`. Not runtime behaviour.

## Deep-link query

`indexLoad` reads:

- `page`
- `params` as URI-encoded JSON, or separate `userID` and `eventID`
- `srid` on `screen_result_review`

External pages set `parameters.externalLink` and hide `#footer-bar`, `#menu_icon`, `#user_icon`, and `#users_icon`.

## Health certificate and QR

`doScanner` constructs `QrScanner` on `#qr-video`, lists cameras, and can scan an image file via `QrScanner.scanImage`. Results land in `#qrScannedCode`. `loadPage` calls `scanner.stop()` when a scanner instance exists.

`doSaveCertificate` for type `SCAN` does not POST. The toast text is "Still awaiting API CODE!".

`renderPDF` uses PDF.js `getDocument` on a data URI. `doCertUpload` treats `data:image/pdf` as PDF and jpeg/gif/png as images.

## Service worker

Cache name `Cache-v3.06`. `install` caches the `REQUIRED_FILES` list (shell, content HTML, scripts, styles, highlights, font CSS, Google Fonts stylesheet). `fetch` answers with the cache match. The file's closing comment says `claim()` is used so the worker takes control.

`_manifest.json` comments say its `version` must match `data-pwa-version` on the manifest link or an update loop occurs. `index.html` sets `data-pwa-version="set_in_manifest_and_pwa_js"`. The manifest `version` is `"1.0"`. Those two strings are not equal. **Inferred:** the warning in the manifest is not satisfied by the current attribute. Whether that still causes an update loop depends on theme code in `scripts/custom.js` looking up that attribute. This was not executed in a browser for this document.

## Deployment

`bitbucket-pipelines.yml` uses image `atlassian/default-image:2`.

| Branch | S3 variables | CloudFront variables | `deployment:` on the S3 step |
|---|---|---|---|
| `qa` | `QA_AWS_ACCESS_KEY_ID`, `QA_AWS_SECRET_ACCESS_KEY`, `QA_AWS_DEFAULT_REGION`, `QA_AWS_S3_BUCKET` | `QA_CLOUDFRONT_DISTRIBUTION_ID` | `production` |
| `prod` | `FULL_PROD_AWS_*`, `FULL_PROD_AWS_S3_BUCKET` | `FULL_PROD_CLOUDFRONT_DISTRIBUTION_ID` | `production` |
| `master` | `PROD_AWS_*`, `PROD_AWS_S3_BUCKET` | `PROD_CLOUDFRONT_DISTRIBUTION_ID` | `production` |

Pipes: `atlassian/aws-s3-deploy:0.3.8` with `LOCAL_PATH: $BITBUCKET_CLONE_DIR`, then `atlassian/aws-cloudfront-invalidate:0.3.3`. No exclude list is written in the YAML. The `prod` branch is not on the cloned remote. All three steps are labelled `deployment: production` inside Bitbucket's deployment keyword, including `qa`.

Public URL, bucket names, and whether pipelines still run are **Unknown / Requires Confirmation**.

## Local development

No README, Docker file, or env example. Scripts expect to be served from the site root because of absolute `/scripts` and `/plugins` URLs. `requestAPI` will call the production Footprint host unless `debug` is set true in source.

`sonar-scanner.bat` expects a local SonarScanner install at `C:\sonar-scanner`. `.scannerwork/` in the clone is scanner output, not runtime code.

## Security notes (as implemented)

- Passwords and the auto-login constant travel in the browser and in request bodies.
- Session is readable and writable `localStorage`.
- API calls are unauthenticated beyond whatever the JSON body contains (`AMID`, reference, password).
- `php/contact.php` would mail `$_POST` fields to `mail@domain.com` with the posted address as `From`, if something invoked it. The shell does not.
- Certificate and profile images are base64 in JSON and in `localStorage`.
- Registration terms HTML from the API is assigned with `innerHTML`.

These are observations. They are not a test report.

## Related repositories

| Repo | Relationship established from this tree |
|---|---|
| `mypass-registration` | Separate Bitbucket repo. Silicon Ark docs date its split to 2022-02-11, the same day as `d76cabf` "Branch Split , Master is production". This repo still contains `registration_form.html`. |
| `track.mypass.zone` | Not referenced by these scripts. It is a different codebase that also calls `footprintapp.net`. |

## Monitoring and jobs

No application logs, metrics, queues, or background workers are in this repository. Pipeline failure behaviour is whatever Bitbucket does when a pipe fails. The client does not retry failed API calls.

## Testing

No test files and no test step in the pipeline. Verification of this document was by reading source and `git log`, not by running the app.
