# Technical documentation — FootPrintLive

Evidence date: 2026-10-14. Source: `git@bitbucket.org:overdrive/footprintlive.git`, `master` at `e54fddb` (2019-09-10, "First commit"). Remote also has `development` (`6620f7e`, 2019-11-19, "Changes to VAP API's") and `acc-tyrone` (`38e3150593b3aad5661b42af347d75f6971695b4`). Only `master` was read.

Provenance labels: **Documented**, **Implemented**, **Inferred**, **Unknown**.

## Architecture

Monolithic PHP application on Zend Framework 1.11.10 (`library/Zend/Version.php`, `const VERSION = '1.11.10'`).

Request path:

1. Repository root `.htaccess` rewrites any URI that does not already start with `/public/` into `public/`.
2. `public/.htaccess` leaves existing files and directories alone and sends everything else to `index.php`.
3. `public/index.php` defines path constants, puts `library/` on the include path, requires `Zend/Application.php`, `Other/Functions.php`, and `Other/Notifications.php`, starts a Zend session, and runs the application.
4. `APPLICATION_ENV` comes from the environment, or `production` when unset.
5. `PG_Controller_Plugin_LayoutPicker` sets the layout name to the current module name before dispatch.
6. Controllers use `Zend_Db_Table` models. The default adapter is PDO MySQL from `application.ini`.

There is no separate API process, queue worker, or frontend build. JSON endpoints are Zend controllers that `echo json_encode(...)`.

Provenance: **Implemented**.

## Repository layout

```text
.htaccess                 rewrite into public/
phpinfo.php               unguarded phpinfo
mssql.php                 RDS MSSQL connect probe
boksmartmssql.php         BokSmart MSSQL query probe
changelog.txt             Release 1 notes
footprint_changelog.txt   empty
application/
  Bootstrap.php
  configs/application.ini
  layouts/                one phtml per module, plus test.phtml
  models/                 Zend_Db_Table classes and models/DbTable
  modules/                accreditations, admin, api, app, default, gir,
                          live, printers, pub, referee, union, union_old
library/
  Zend/                   framework
  PG/                     project helpers
  Other/                  Functions.php, Notifications.php
public/                   front controller, assets, PHPExcel, tcpdf, dompdf,
                          SparkPost client, class/sms.php
```

File counts on the inspected tree: `application` 2055, `library` 2894, `public` 4234.

`application/configs/` also contains `application - Copy.ini`, `application - Copy (2).ini`, and `application.ini.bak.240519`. Runtime uses `application.ini` only.

Provenance: **Implemented**.

## Runtime configuration

`[production]` in `application/configs/application.ini`:

| Key | Value |
|---|---|
| `phpSettings.display_errors` | 0 |
| `resources.frontController.moduleDirectory` | `application/modules` |
| `resources.layout.layout` | `default` |
| `resources.locale.default` | `af_ZA` |
| `resources.session.cookie_lifetime` | 864000 |
| `resources.db.adapter` | `pdo_mysql` |
| `resources.db.params.host` | `localhost` |
| `resources.db.params.dbname` | `teamwizz_SARU` |
| `resources.db.params.username` | `teamwizz_ADMIN` |

The password is present in the file and is intentionally omitted here.

`[staging]` inherits production with no overrides. `[testing]` and `[development]` turn display errors on. `[development]` also sets `displayExceptions` to 1.

An extra block `apilogs.db.params` names host `localhost` and database `teamwizz_API` with the same account. It is not a `resources.db` entry, so Zend will not open it unless some class reads those keys. No such reader was found in the search that was done. Provenance: **Implemented** keys, use **Unknown**.

`Bootstrap.php` contains a commented `_initDb` that would have connected to host `footprintapp.net` and database `evolveci_sarugby`. It does not run. Provenance: **Implemented** as a comment.

`public/index.php` path constants: `UPLOADS_PATH` `public/uploads`, `DOCS_PATH` `public/xls`, `FILES_PATH` `public/files`, `CLASS_PATH` `public/class`, `CLASSES_PATH` `public/Classes`, `TCPDF_PATH`, `IMG_PATH` `public/IMGS`, `AC_PATH` `public/accre`, `SITEDOC` `public/TermsText`, `LOCALDATA` `public/local_data`, `ART_PATH` `public/artists`, `PLS_PATH` `public/players`. Several of those directories are missing or gitignored (see Storage).

Memory limit at boot is 200M. Individual controllers raise it (cron 180M, API often 8000M, accreditations 800M).

## Modules and routing

Zend default routing: `/{module}/{controller}/{action}/param/value`. The default module omits the module segment, so `/login` is `default` / `Login` / `index`.

| Module | Layout file | Notes |
|---|---|---|
| `default` | `default.phtml` | Back office and login |
| `admin` | `admin.phtml` | |
| `union` | `union.phtml` | Index redirects to squads |
| `referee` | `referee.phtml` | |
| `app` | `app.phtml` | |
| `gir` | `gir.phtml` | Index redirects to squads |
| `accreditations` | `accreditations.phtml` | Index redirects to collections |
| `live` | `live.phtml` | Scoring disables layout |
| `printers` | `printers.phtml` | |
| `pub` | `pub.phtml` | |
| `api` | none used | Actions disable layout and view renderer |
| `union_old` | no dedicated line in the ini layout list | Plugin still sets layout name to `union_old`. A matching layout file was not in `application/layouts/` |

Provenance: **Implemented**.

`ini` keys such as `admin.resources.layout.layout` are not standard Zend resource prefixes. The layout that actually applies is the one `LayoutPicker` sets from the module name. Provenance: **Inferred**.

## Authentication

- Adapter: `Zend_Auth_Adapter_DbTable`.
- Table: `UserLogin_view`. Columns: `Username`, `Password`.
- After success, storage is overwritten with `Model_DbTable_Profile::getForSeason`.
- `Role` on that profile is JSON. The menu reads it. See `business-rules.md`.
- Logout: `Zend_Auth::clearIdentity()` and `Zend_Session::destroy()`.
- Password reset key column: `ResetKey` on the credentials model (table not re-read; the model is `Model_Credentials`).
- Passwords written by reset are MD5.

Provenance: **Implemented**.

## Databases

### MySQL (application)

Adapter `pdo_mysql`, database name `teamwizz_SARU`, host `localhost` in the ini. No `.sql` dump is in the repository. Tables below are the `protected $_name` values on models. Duplicates mean more than one class maps to the same table.

People and access: `profile`, `oldprofile`, `UserLogin_view` (auth, not a model `$_name`), `ef_users`, `ef_userdetails`, `user_type`, `usermeta`, `privileges`, `Company_Members`, `users_remove`.

Organisations and places: `ef_unions`, `ef_provinces`, `ef_union_municipalities`, `ef_municipality`, `Municipalities`, `Municipality_District`, `provinces`, `suburb`, `stadiums`, `Schools`, `ef_institutions_type`, `fp_org_levels`.

Squads and players: `squad`, `squad_players`, `Squads_players`, `Squad_Personnal`, `Squad_Lineup`, `SquadType`, `SquadAdmission`, `SquadProfileImage`, `squad_images`, `squads_history`, `SquadsComments`, `oldSquads`, `positions`, `players_history`, `PlayerCareer`, `TotalCareer`.

Fixtures and matches: `Fixture`, `FixtureDoc`, `Fixture_Notifications`, `fixture_score`, `team_scores`, `team_score_audit`, `Fixture_Scorers`, `Match_Report`, `Match_Subtitutions`, `Player_Fixture_Time_Played`, `match_officials`, `matchEvents`, `Comentry` model `ComentryAndCiting` (table name not re-read).

Tournaments: `tournament`, `Tournament_structure`, `Tournament_selectors`, `TournamentLogs`, `TournamentMedia`, `Tournament_Notifacations`, `Tournament_Foodsessions`, `TounamentRanks`, `series`, `SeriesLogs`, `pool_names`, `Leagues`.

Accreditation: `AccreditationTypes` (also used by `ZoneTypes`), plus classes whose `$_name` was not all listed in the first grep page (`AccreditationList` and related). The cron uses `Model_AccreditationsApplications`, `Model_AccreditationApplicantsServices`, `Model_AccreditationZone`, `Model_AccreditationList`.

Medical and documents: `PlayerInjury`, `PlayerInjuryFollowUp`, `Documents`, `document_type`, `project_file`.

Other domain tables seen: `TransferRequest`, `TransferType`, `Ethnicity`, `courses`, `assessTempStructure`, `assessTempAccess`, `ScoutedPlayers`, `ScoutAssessments`, `ScoutMatches`, `News_Articles_SA_Rugby`, `sms`, `Template_email`, `Email_report`, `grants`, `grantsrequest`, `epg`, `EPG_Reports`, `ef_efiling`, `governance`, `Gir_Report`, `gir_profile`, `Nutritions`, `SessionFood_Items`, `Menu_Venues`, `Allergens` (model exists; `$_name` not in the truncated listing).

`public/database.sqlite3` is in the tree. No PHP reference to that filename was found. Its role is **Unknown**.

Provenance: **Implemented** as class metadata. Live schema was not queried.

### Microsoft SQL Server

`boksmartmssql.php` calls `mssql_connect` to `41.164.24.180:52111` and runs:

```sql
SELECT CAST(BokSmartNumber AS TEXT) as BokSmartNumber, ExpiryDate
FROM Officials
LEFT JOIN Courses ON Officials.CourseId = Courses.CourseId
WHERE BokSmartNumber = '...'
```

The script prints the number and an expiry formatted `Y-m-d`. Credentials are in the file and are not copied here.

`mssql.php` connects to `footprintdb.cunkmhm0dyjb.eu-west-1.rds.amazonaws.com:1433` and closes the link. No query.

`TestController` in the default module has actions that build a similar BokSmart `IN (...)` query and write `boksmart` back onto profiles. That is application code, separate from the root script.

Provenance: **Implemented**. Whether either host still accepts connections is **Unknown**.

## HTTP API

Base path `/api/{controller}/{action}`. Responses are JSON bodies with layout disabled. There is no API key header check in the `init` methods that were read.

Notable write: `POST` parameters `fid` and `comment` on `/api/fixtures/uploadcommentary` are stored as `{fid}comments.json`.

`Api_LoginController::loginAction` parameters: `UserName`, `Password`.

Date-scoped list actions take `date`.

Provenance: **Implemented**. A formal route list or OpenAPI file does not exist.

## External integrations

| Integration | Client | Endpoint or address | Used by |
|---|---|---|---|
| MyMobileAPI | `public/class/sms.php` class `MyMobileAPI` | `http://www.mymobileapi.com/api5/http5.aspx` | Referee, pub, live referee, squad, fixture, assessment, accreditation, SMS controllers |
| Mail | `Zend_Mail` | From addresses seen: `support@footprintapp.net`, `support@footprint.net`, `accreditation@footprintapp.net`, `accreditation@sarugby.co.za` | Login reset, cron approval |
| MyPass HTML | `file_get_contents` of `/pdf/mypass/id/{AAID}` then dompdf | Same host as the cron request | `CronController::mypass` |
| AppWiz | cURL multipart POST | `https://fsrugby.appwizard.co.za/scripts/AppWiz.dll` | `senddata_to_Api` (caller commented out) |
| Font Awesome | Layout link | `https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css` | `default.phtml` |
| SparkPost | `public/SparkPost/*.php` | Not called from `application/` | Unwired library |

SMS and database passwords sit in source. This document does not repeat them.

## Cron and background work

There is no crontab in git and no queue daemon.

`CronController` is a web controller:

- `/cron/autoruntoo` runs `schedual_test` and returns HTML that reloads `https://footprintapp.net/cron/autoruntoo` every 10 seconds.
- `/cron/schedualing` runs `schedual_test` and exits.
- `schedual()` exits immediately.
- Other actions on the same class: `queingold`, `testarea`, `getaccre`, `readfile`, `matches`, `logs`, `view`, `getfixtues`.

`public/cron.txt` contains only `18-03-30 13:07:42`.

Provenance: **Implemented**. What used to hit that URL on a schedule is **Unknown**.

## Documents, PDF, and spreadsheets

- PHPExcel is loaded from `Classes/PHPExcel.php` (`CLASSES_PATH`, `public/Classes`). Member export uses it.
- dompdf is loaded from `dompdf/dompdf_config.inc.php` for the MyPass PDF. Paper size is a custom `array(0, 0, 778, 1440)` portrait, 72 dpi.
- TCPDF path constant points at `public/tcpdf`. Tournament code references PDF downloads (`pdflogsAction`, `refassementpdfAction`). Which calls use TCPDF versus the PG FPDF helpers was not fully traced.
- `library/PG/Controller/Plugin` also contains `fpdf.php` and `html2fpdf.php`.

## Front-end assets

Server-rendered phtml. Libraries linked from the default layout include jQuery UI 1.12.1, Bootstrap CSS, DataTables, FullCalendar, Cropper (`/dist/cropper.css`), a timepicker, multi-select, and Font Awesome 4.7. An older stylesheet set lives under `public/cssold`. Browser fallback images link to Chrome, Firefox, and Safari download pages.

No npm or webpack manifest is in the repository.

## Storage

`.gitignore` excludes:

- `public/accre/achive/`
- `public/accre/assets.zip`
- `public/IMGS/`
- `public/local_data/images/`
- `public/error_log`
- `public/adcs.zip`
- `public/html.zip`

Those paths can exist on a server and be absent from git. `IMG_PATH` points at the ignored `public/IMGS/` directory.

Tracked files that are operational leftovers include root `error_log`, `public/database.sqlite3`, sample JSON comment files (`4794comments.json` and similar), and `public/SMS.txt`.

Uploads referenced by constants (`public/uploads`, `public/files`, `public/xls`, `public/artists`) were not all present as populated trees in the listing that was taken. **Unknown** which of them are created at runtime.

## Security observations (as implemented)

These are facts about the tree, not a remediation plan.

- `phpinfo.php` is in the project root, which the root rewrite exposes under `/phpinfo.php` unless the server document root is already `public/`. If the document root is the repository root, the rewrite serves it through `public/` only when the URI does not start with `/public/`. A URI `/phpinfo.php` is rewritten to `public/phpinfo.php`, and `public/` has no `phpinfo.php`, so the front controller would receive it. A URI that hits the file directly depends on the vhost. **Requires Confirmation** which directory is the Apache document root. The file itself is still in git.
- Database, SMS, and MSSQL credentials are committed.
- MD5 passwords and a hardcoded login override.
- Reset email contains the new password.
- Cron and several API actions have no auth check.
- SQL fragments concatenate request values.
- `display_errors` is off in production config. `error_log` shows warnings were written on a host using timezone `Africa/Harare` on 28 May 2019.
- Comment files and `uploadcommentaryAction` write JSON into the working directory.

## Deployment and environments

No Dockerfile, CodeDeploy `appspec`, Bitbucket pipeline, or README setup steps exist on `master`.

The only environment switch is `APPLICATION_ENV` (`production` default, plus `staging`, `testing`, `development` sections that do not change the database host).

Hostnames that appear as literals: `footprintapp.net`, `www.saruefiling.com`, `sarugby.co.za` mail, `fsrugby.appwizard.co.za`.

How a release was copied to a server is **Unknown**.

SonarQube files listed for the scan host at task creation (`sonar-project.properties`, `sonarqube_scan.bat`) are not in the git tree.

## Development and testing

No PHPUnit, no `tests/` directory, no CI config.

Modules contain controllers whose names are Test, Mytest, or Squadtest. They are ad hoc data-fix and probe actions (BokSmart imports, mail tests, squad moves), not an automated suite.

`changelog.txt` is the only change log with content. Entries are dated, signed "HDP", and name a file and a function.

Git history on `master` is one commit, so blame cannot separate the May 2019 edits from the rest of the import.

## Dependencies (vendored, no lockfile)

| Piece | Where | Version evidence |
|---|---|---|
| Zend Framework | `library/Zend` | 1.11.10 |
| PHPExcel | `public/Classes` | "Office 2007 XLSX" comments in the export. Package version **Unknown** |
| TCPDF | `public/tcpdf` | **Unknown** version |
| dompdf | `public/dompdf` | **Unknown** version |
| SparkPost PHP client | `public/SparkPost` | Present, unused by application code |
| jQuery UI | `public/jquery-ui-1.12.1` | 1.12.1 from the directory name |
| Font Awesome | CDN | 4.7.0 |

PHP version required by Zend 1.11 is not declared in-repo. The `mssql_*` functions in the root scripts need the old MSSQL extension, which current PHP does not ship. Provenance: **Inferred** from the function calls. The PHP version that last ran this tree is **Unknown**.

## Related repositories

`silicon_ark/track.mypass.zone` describes another Zend 1 application whose ini uses database name `teamwizz_SARU` and whose models overlap this tree (fixtures, squads, food, news). That document infers it was cut from a larger SARU application. FootPrintLive is a candidate for that larger tree. Sharing was not proven by a database connection. **Requires Confirmation**.
