# Technical documentation — website (1 For The Road)

Evidence date: 2026-09-28. Source: `git@bitbucket.org:overdrive/website.git`.

Secrets are named by file. Values for the database password and the reCAPTCHA secret are not copied here.

## Repository

| Item | Value |
|---|---|
| Origin | `git@bitbucket.org:overdrive/website.git` |
| Default branch | `master` (`origin/HEAD`) |
| Default tip | `581c5d9` — 2023-05-05 — "update new code" — Jaco Brits |
| Other remote branch | `origin/development_russel` at `a87b0c5` — 2021-06-25 — Russel Sauer |
| Common ancestor | `bbdc3a0` — 2021-04-21 — "basic start" |
| Tags | None found |
| README, license, changelog | None in either tree |
| Tests | None found |
| CI | None found (no pipeline file, no `sonar-project.properties` in git) |

`master` after the split contains only `index.html` analytics edits. The membership application and `webadmin` exist only on `development_russel`.

A scan that created the onboarding task listed `sonar-project.properties` and `sonarqube_scan.bat` at the root. They are not in either branch. **Unknown / Requires Confirmation**.

## Architecture

### `master` — static theme

```text
index.html
  ├── css/ js/ fonts/ images/     (theme assets at repo root)
  ├── Matomo loader               (analytics.medmin.co.za, site 5)
  └── links to *.html             (files actually live in template/)
template/
  ├── *.html                      (Prime Cab pages)
  ├── contact/*.php               (theme mailers)
  ├── mailchimp/subscribe.php
  └── duplicated css, js, fonts
js/api/                           (Twitter OAuth helper)
```

No build step. Files are served as stored.

### `development_russel` — static marketing site plus PHP admin

```text
*.html, contact.php, register.php     public site
system.php                            host → database settings, mysqli connect
_nemo.basic.cls.php                   front controller base
webadmin/
  login.php, index.php, *.php         entity screens
  _nemo.*.cls.php                     framework
  includes/*.cls.php                  domain classes
  layouts/                            admin chrome
  SESSION/                            session path configured for production
                                      (directory itself was not in git)
```

Public pages from the 2021 redesign are hand-written HTML. They do not render through the Nemo layouts. PHP is used for `register.php`, `contact.php`, `system.php`, and `webadmin`.

Older Nemo front layouts remain in `layouts/` (`layout.front.incl.php`, `layout.eatout.incl.php`, `layout.food24.incl.php`, and others). They share a keyword meta string about drinking and driving. **Unknown** whether any route still includes them.

## Languages and libraries

| Layer | What is in the tree |
|---|---|
| Markup | HTML5, inline CSS, Bootstrap markup (navbar, grid, accordion) |
| CSS | Vendored Bootstrap, Owl Carousel, Slick, Font Awesome, icomoon, a large `style.css`, colour-switcher CSS on the theme |
| JavaScript | jQuery 1.12.5, `migrate.js`, Bootstrap JS, Owl Carousel, custom page scripts inline in the HTML |
| Fonts | Glyphicons, icomoon, Slick, Stroke-Gap; Font Awesome webfonts on `development_russel` |
| Server | PHP. Version **Unknown**. Extensions used: `mysqli`, `json`, `mail` via `mail()`, sessions |
| Data | MySQL through `mysqli`. Database name configured as `1fortheroad` |
| Package managers | No `composer.json`, `package.json`, or lockfile |

Font Awesome Pro is also linked from a CDN on the russel homepage (`https://pro.fontawesome.com/releases/v5.10.0/css/all.css`) with an integrity attribute. Local Font Awesome files exist as well.

## Application structure (`development_russel`)

### Request paths

| URL (file) | Role |
|---|---|
| `index.html`, `aboutus.html`, `packages.html`, `whyjoin.html`, `faq.html`, `404.html` | Static |
| `contact.html` → `contact.php` | Email |
| `register.html` → `register.php` | Membership insert |
| `webadmin/login.php` | Staff auth |
| `webadmin/*.php` | One PHP file per entity, class under `webadmin/includes/` |

### Nemo pattern

Entity screens construct a page object, point it at a table (`new NemoDatabase("tblClient", …)`), and use list SQL plus a save of `$db->Fields`. Queries are string-built. Some values pass through `$db->qs()`; many admin and registration statements interpolate `$_POST` directly.

Email goes through `NemoEmail` (`webadmin/_nemo.email.cls.php`), which sends with PHP `mail()`.

Menus are rows in `tblMenuLevel1` and `tblMenuLevel2`, filtered by the session security group.

### Domain tables referenced by code

`tblClient`, `tblClientPackage`, `tblPackage`, `tblVehicle`, `tblDriver`, `tblBooking`, `tblTripBooking`, `tblChild`, `tblArea`, `tblInvoice`, `sysUser`, `sysSecurityGroup`, `sysRegistration`, `sysSpam`, `sysMenuLevel2` / `tblMenuLevel1` / `tblMenuLevel2`.

There is no canonical schema file. Column names below are the ones assignments and queries use. The live table may have more columns.

`tblClient` fields written by registration: `strMembershipNumber`, `strClient`, `strID`, `strEmail`, `strPhone`, `strCell`, `strWork`, `txtAddressHome`, `txtAddressPostal`, `strPostalCode`, `refAreaID`, `strAccountHoldersName`, `strAccountNumber`, `strAccountType`, `strBankName`, `strBranchCode`, `strSurvey`, `blnActive`, `dtRegistered`, `strFirstUser`, `strLastUser`, `dtFirstEdit`.

Admin client code also uses `refMasterID`, `blnMasterPaysSubs`, `blnMasterPaysUsage`, `strArea` as a foreign key onto `tblArea.AreaID` (constraint text is in a comment in `client.cls.php`).

`tblClientPackage`: `refClientID`, `refPackageID`, `dblPrice`, `dblMinCharge`, `dblFreeKM`, `dblMinimumTrip`, `dblChargePerKM`, `dblAmount`, `intQuantity`, `blnActive`, user and date stamps.

`tblPackage`: `PackageID`, `strPackage`, `dblPriceInc`, `dblMinCharge`, `dblFreeKM`, `dblMinimumTrip`, `dblChargePerKM`, `blnFamilyDiscountPackage`.

`tblVehicle`: `refClientID`, `strVehicle`, `strRegistration`, `strColour`, `blnDefault`, `dateLastUsedOn`.

`tblBooking.refStatus` values are documented in `business-rules.md`. Other booking columns used in list or trip update: `dateBookingDate`, `strPickupTime`, `refClientID`, `refDriverID`, `refTripBookingID`, `strTripDescription`, `txtNotes`, `chkCancelled`, `chkCancelledBillable`.

`tblInvoice`: `strPeriod`, `blnSystemGenerated`.

## Environment configuration

`system.php` on `development_russel` selects a settings object from `$_SERVER[SERVER_NAME]`.

| Host key | What the file sets |
|---|---|
| `localhost` | Database name `1fortheroad` |
| `lamp` | Database name `1fortheroad` |
| `www.1fortheroad.co.za` | Host `sql24.jnb1.host-h.net`, user `DBU_OFTR`, database `1fortheroad`, session path `{DOCUMENT_ROOT}/webadmin/SESSION/`, `SERVER_PROTOCOL` `HTTPS`. Password is in the file and is omitted here |
| `1fortheroad.co.za.www452.jnb1.host-h.net` | Same production database settings |
| `www.14ya.co.za` and `14ya.co.za.www452.jnb1.host-h.net` | Database name `1fortheroad` |
| Commented | A `dev.overdrive.co.za` block is commented out |

If `SERVER_NAME` is `1fortheroad.co.za`, the script replaces it with `www.1fortheroad.co.za`. The same redirect pattern is applied for the 14ya apex host.

Connection is `mysqli_connect`. On failure the system message is `Database Connection has Failed!` plus `mysqli_connect_error()`.

An older `mysql_connect` call is commented out above the mysqli call.

**Security fact:** the production password is committed in `system.php`. The reCAPTCHA secret is committed in `register.php` and `contact.php`. Both need human review and rotation. This document does not repeat them.

SMTP is not configured in `system.php`. Outgoing mail uses `$SystemSettings["SMTP Send As"]` and `$SystemSettings["SMTP BCC"]`, which are loaded by the Nemo settings layer. Commented lines show addresses that were tried during development (`info@1fortheroad.co.za`, and personal mailboxes). Those comments are not the active assignment.

## Authentication and sessions

Staff only. Members do not get an account in this codebase.

- Table `sysUser.strPasswordMD5`, compared with `md5($strPassword)`.
- Session key `$_SESSION[USER]` with `ID`, `USERNAME`, `EMAIL`, `SECURITYGROUPID`.
- `login.php` calls `session_destroy()` before a successful attempt, then `session_start()` inside the login branch.
- Production session save path is `webadmin/SESSION/` under the document root.
- Menu and `blnView` enforce which admin pages a group may open. This is application-level checking, not database row security.

Public forms have no session. They rely on reCAPTCHA and the spam table.

## Integrations

| Integration | Where | Behaviour |
|---|---|---|
| Google reCAPTCHA v3 | `register.html`, `contact.html`, `register.php`, `contact.php` | Browser executes the site key (action `homepage`). Server calls `https://www.google.com/recaptcha/api/siteverify` with `file_get_contents` |
| MySQL | `system.php` | See environment table |
| PHP `mail()` | `NemoEmail` | Register welcome mail; contact notification; 14ya booking mails in `bookingYA.cls.php` |
| Matomo | `master` `index.html` only | `//analytics.medmin.co.za/matomo.php`, site id `5`, cookie domain `*.1fortheroad.co.za`, link tracking. Previous host `analytics.siliconsoftware.net` site id `3` |
| Font Awesome CDN | Russel `index.html` | Stylesheet only |
| South African COVID portal | Banner | Ordinary hyperlink |
| Twitter OAuth | `js/api/` on both branches | Theme helper. Not used by the 1 For The Road pages reviewed |

No queue, cron definition, or worker process is in the repository. Invoice periods are read (`Max(strPeriod)` where `blnSystemGenerated = 1`). What creates those rows on a schedule is **Unknown**.

`webadmin/sweeper.php` exists. Its business effect was not determined.

## Deployment and infrastructure

No Dockerfile, server config, or pipeline is in git.

Hostnames `sql24.jnb1.host-h.net` and `www452.jnb1.host-h.net` are consistent with xneelo (Hetzner) shared hosting. That hosting inference is **Inferred** from the names, not from a contract in the repo.

`SERVER_PROTOCOL` is set to `HTTPS` for the production 1 For The Road host entry. Certificate management is outside the repo.

How files are copied to the host (FTP, git pull, panel) is **Unknown**.

## Security notes (from the code, not a pentest)

- Database password and reCAPTCHA secret are in git on `development_russel`.
- Registration writes `serialize($_POST)` into `sysRegistration`, which includes bank account numbers.
- Several SQL statements concatenate request values. `client.cls.php` and `register.php` show both quoted interpolation and some `qs()` usage.
- Staff passwords are unsalted MD5.
- `contact.php` calls `Send()` and then evaluates `Send()` a second time.
- Delete protection for billable cancellations compares a different status string from the one save writes (`cb: CancelledBillable` versus `cb: Cancelled Billable`).
- `login.php` failure log messages use the spelling "Loggin failed".

## Development and testing

No documented local setup beyond the `localhost` and `lamp` keys in `system.php`.

No PHPUnit, no fixture, no seed, no test data that is clearly marked as fake. `webadmin/zSandBox.php` and `webadmin/system.functions.inc.php.bak` are present. Profile images under `webadmin/profilepictures/` are committed.

The theme on `master` can be opened as static files. PHP forms need a PHP runtime. The admin needs MySQL and the Nemo include path.

## `master` technical notes

- `.gitignore` is the Atlassian sample (node_modules, class files, logs, IDE, large video). It does not ignore `system.php` or env files. `development_russel` was not compared line-by-line for ignore rules.
- Root and `template/` duplicate the theme assets. The root homepage's document-relative links do not include `template/`.
- jQuery file name is `jquery-1.12.5.min.js`.
- IE conditional comments load html5shiv and Respond from `oss.maxcdn.com`.

## File map for the product branch

```text
index.html aboutus.html packages.html whyjoin.html
faq.html contact.html contact.php register.html register.php
404.html system.php _nemo.basic.cls.php
layouts/ modules/ pdfs/
webadmin/login.php webadmin/index.php
webadmin/client.php webadmin/booking.php webadmin/bookingTrip.php
webadmin/bookingYA.php webadmin/invoice.php webadmin/invoiceYA.php
webadmin/package.php webadmin/pay.php webadmin/driver.php
webadmin/vehicle.php webadmin/area.php webadmin/child.php
webadmin/schedule.php webadmin/report.php webadmin/user.php
webadmin/security.group.php webadmin/settings.php
webadmin/sweeper.php webadmin/message.php webadmin/usage.log.php
webadmin/includes/*.cls.php
webadmin/_nemo.*.cls.php
```

## Unknown / requires confirmation

1. PHP version and the MySQL version on `sql24.jnb1.host-h.net`.
2. Whether `webadmin/SESSION/` is writable in production and is excluded from backups.
3. Live values of `SMTP Send As` and `SMTP BCC`.
4. Whether eatout/food24 layouts are still routed.
5. What `sweeper` does operationally.
6. Whether Sonar files exist only on a scan machine outside git.
7. Which branch is actually published.
