# Business rules — myPass-App

Evidence date: 2026-10-09. Inspected revision: `master` at `d8d04bf`.

Rules below are taken from `scripts/core.js` and `scripts/core2.js` unless noted. **Inferred** means the code behaves this way and no separate policy document states it. Do not treat an inference as an approved policy.

`docs/BIL_Tour-COVID-19_Protocol_Final.pdf` is in the repository and was not transcribed. If that PDF is the protocol, these client rules may disagree with it. That comparison is **Unknown / Requires Confirmation**.

## Access

| ID | Rule | Label |
|---|---|---|
| BR-001 | A person with no `MyPass-LoggedInUserData` and no deep-link query is sent to the sign-in page. | **Implemented** |
| BR-002 | Sign-in requires a reference number and a password. The reference is sent in upper case. `getlogin` must return `login == 1`. | **Implemented** |
| BR-003 | The client stores the `getlogin` `data` array in `localStorage` and treats that as the session. No token, cookie, or expiry check is implemented. A comment in `indexLoad` says "todo: verify users credentials" and does not do it. | **Implemented** |
| BR-004 | Deep-link auto-login calls `getlogin` with the URL reference and a fixed password literal in `userAutoLogin`. | **Implemented**. Whether the API still accepts that password is **Unknown / Requires Confirmation**. |
| BR-005 | If auto-login's returned reference does not equal the URL `userID`, the client clears `localStorage`. | **Implemented** |
| BR-006 | If the deep link has no user id, the client invents a local profile (`blankPerson`) with `FirstLogin` `"N"` and an empty reference. | **Implemented**. **Inferred:** this is a guest path, not a verified account. |
| BR-007 | Sign-out clears all of `localStorage`. | **Implemented** |
| BR-008 | External symptom and review screens hide the main navigation. | **Implemented** |

## Password

| ID | Rule | Label |
|---|---|---|
| BR-009 | Verify-account requires a reference, a mobile number of at least 10 characters, and accepted terms. A leading `0` is removed before `getpwdreset`. | **Implemented** |
| BR-010 | A new password must be at least 6 characters and must match the confirmation. | **Implemented** |
| BR-011 | `postpwd` and `getlogin` send the password as JSON text. This revision does not hash it. | **Implemented** |
| BR-012 | Profile save sends `postpwd` only when the password field is non-empty. Profile fields are still saved if that call fails. The password failure is a toast only. | **Implemented** |
| BR-013 | "Forgot Password?" and "First Login" open the same verify sheet. | **Implemented**. **Inferred:** the product does not distinguish those two intents in this client. |

## Profile

| ID | Rule | Label |
|---|---|---|
| BR-014 | If any event for the person has `StatusDescription` equal to `Approved`, the profile edit control is unbound and recoloured grey. | **Implemented**. **Inferred:** an approved accreditation locks profile editing. |
| BR-015 | `AccreditationStatus` is stored on the home screen and never read. It does not lock the profile. | **Implemented** |
| BR-016 | Gender values used on the profile are `M`, `F`, and empty. Symptom check also uses `N` ("prefer not to say"). | **Implemented** |
| BR-017 | Birth year choices start at 1930 and end at the current calendar year. The registration form pre-selects 1990. | **Implemented** |
| BR-018 | Displayed names, ids, and addresses are trimmed. Blank profile view fields show `n/a`. | **Implemented** |

## Events and pass

| ID | Rule | Label |
|---|---|---|
| BR-019 | The pass, the upcoming test, and symptom entry use the first event returned by `geteventsperuser` (`response[0].AC`). | **Implemented**. **Inferred:** "first" is whatever order the API uses. The client does not sort. |
| BR-020 | Missing event name or role description is shown as `n/a`. | **Implemented** |
| BR-021 | An empty pass QR payload is replaced with the text `NoCode`, and that text is encoded as the QR. | **Implemented** |
| BR-022 | Status numbers colour the UI: 1 blue, 2 orange, 3 green, 4 red, anything else grey. The client does not name these states, except vaccine `certStatus == 1` is shown as "Yes" (colour 3) and any other vaccine status as "No" (colour 2). | **Implemented**. The business meaning of codes 1–4 is **Unknown / Requires Confirmation**. |
| BR-023 | The registration form always sends event id `304` (`staticEventID`). | **Implemented** |
| BR-024 | Logged-out symptom and review links force event id `346`. Auto-login's screening payload and the extra accreditation post use event id `345`. | **Implemented**. These three ids are not explained in the repo. **Unknown / Requires Confirmation** which events they are. |
| BR-025 | `domains_old.js` maps labels such as `bil2021` to `304` and `9hour` to `346`. The shell does not load that file, so those labels do not select an event at runtime. | **Implemented** (file present, unused) |

## Symptom check

| ID | Rule | Label |
|---|---|---|
| BR-026 | The active questions are: identity; Covid-19 contact in the last 7 days; symptoms in the past 24 to 48 hours (fever above 38°C, body aches, loss of smell/taste). Yes on symptoms asks which of Fever, Cough, Sore Throat, Body aches, Loss of smell apply. | **Implemented** (copy in the HTML, storage in `core2.js`) |
| BR-027 | No recent symptoms stores an empty symptom list and skips the checkbox step. | **Implemented** |
| BR-028 | High-risk travel (`symptom_step_2`) and untreated conditions (`symptom_step_4`, `symptom_step_4b`) are not asked on the active path. | **Implemented**. **Inferred:** those questions are retired in this revision, or were left behind when the flow was shortened. |
| BR-029 | Step 1 validates ID/passport length ≥ 6, non-empty name, mobile length ≥ 8, and a non-empty email matching the expression in `symptom_screening_submit_handler`. That validation is skipped when `MyPass-external` is `"true"`. | **Implemented** |
| BR-030 | Submit stays disabled until the declaration checkbox "I Accept" is checked. | **Implemented** |
| BR-031 | The declaration names the event's `AccreditationName` as the party allowed to use the answers for on-site Covid-19 risk. | **Implemented** |
| BR-032 | The client shows FAILED when `postsymptomcheck` returns `status == "FAILED"`. It does not decide pass or fail itself. | **Implemented**. The failing conditions are **Unknown** (API). |
| BR-033 | When the stored profile has `FirstLogin == "N"`, step 1 also posts an accreditation for event `345` with terms and covid flags set to `1`. `familyName` on that post is taken from the first-name field. | **Implemented**. **Inferred:** guest or first-login symptom checks are also accreditation applications. The surname mix-up looks unintentional. |
| BR-034 | A symptom-check card on home opens the result only when `HealthTitle` is exactly `SYMPTOM CHECK`. | **Implemented** |

## Health certificates

| ID | Rule | Label |
|---|---|---|
| BR-035 | Certificate type, day, month, year, and status are required. Vaccine type also requires a vaccine name. Batch/code is not required. | **Implemented** |
| BR-036 | A certificate file is required and must be under 3 MB. | **Implemented** |
| BR-037 | Vaccine names the client will display are Johnson & Johnson, Astra-Zeneca, Novovac, Pfizer, Moderna, and Sputnik V, plus N/A for id `0`. | **Implemented** |
| BR-038 | Choosing Symptom Check does not upload a file. It starts a symptom check for the next event, or toasts "Unable to find next event!". | **Implemented** |
| BR-039 | Choosing Scan does not upload a certificate. Save refuses an empty scan and otherwise toasts "Still awaiting API CODE!". | **Implemented** placeholder |
| BR-040 | The home vaccine card treats a missing `certDate` or the string `null` as no vaccination. | **Implemented** |

## Registration form

| ID | Rule | Label |
|---|---|---|
| BR-041 | Categories and roles come from `getevent` for event `304`. Every option is rendered with the HTML `selected` attribute. | **Implemented** |
| BR-042 | Organisation name is filled from `getorganisation` `TradingName` for the typed reference. A failed lookup is only logged. | **Implemented** |
| BR-043 | Gender on the registration post is `F` if `#female` is checked, otherwise `M`. | **Implemented** |
| BR-044 | `tandcCheck` and `covidCheck` are set from `element.value == true`. Both checkboxes have `value="1"` regardless of the checked state, and `"1" == true` is true in JavaScript. The flags are therefore sent as `1` even when the boxes are unchecked. The Covid checkbox only reveals the submit button. | **Implemented**. **Inferred:** the form does not actually enforce those two acceptances. |
| BR-045 | A successful `postaccreditation` shows event name, reference, email, and contact name from the response. This client does not send the confirmation email. | **Implemented**. Email delivery is **Unknown**. |
| BR-046 | The registration page is not linked from the menu. | **Implemented**. Whether it is still a supported journey is **Unknown / Requires Confirmation**. |

## Sign up

| ID | Rule | Label |
|---|---|---|
| BR-047 | Sign-up requires reference, mobile, password, matching confirmation, and the terms checkbox. Email is not required by the validator. | **Implemented** |
| BR-048 | Uniqueness is a comparison against the first row of local `userData.json` only. A non-match alerts and posts to `userDataTest.json`, which is not in the repo. | **Implemented** stub. **Inferred:** this is not a live registration rule. |

## Navigation and chrome

| ID | Rule | Label |
|---|---|---|
| BR-049 | Events, organisation home, organisation events, scan, members, settings, and admin are visible and do not navigate. | **Implemented** |
| BR-050 | Health title "coronavirus" is labelled "Test History". "symptom check" is labelled "Symptom Check History". | **Implemented** |
| BR-051 | Mobile numbers of 10 digits starting with `0` are treated as South Africa (`27`) by `filterMobileNumber`. That helper is not what the live profile and symptom forms use; those forms keep dial code and number in separate fields. | **Implemented** helper, mostly unused on the active path |

## Not rules of this repository

- Pass/fail of a symptom check, approval of an accreditation, and the meaning of status codes are API behaviour. This client displays them.
- `myPass-registration` has its own later registration rules. They are not rules of this tree.
- `track.mypass.zone` permit rules are not rules of this tree.
- Pipeline variable names do not state a business environment policy beyond the branch names `master`, `qa`, and `prod`, and the commit message that calls master production.
