# Technical documentation — quantiviaLive

Evidence date: 2026-10-05.

Source: `git@bitbucket.org:overdrive/quantivialive.git`, `master` at `0af11d2` (2019-08-15, "First commit"). Only branch observed: `master`. `origin/HEAD` → `master`.

The scan-host path `~/projects/sonar_scan/repos/quantiviaLive` was not on this machine. Facts below come from that git revision. Secret values are omitted. Configuration files that contain credentials are named as risks only.

## Architecture

```text
Browser
  │
  ├─ login.php / loginextra.php
  │     └─ header.inc.php → phpgwapi (session cookie)
  │
  ├─ index.php
  │     └─ eGroupware apps (calendar, felamimail, addressbook, trackers, …)
  │
  └─ quantivia/main.php
        ├─ setup/quantivia_setings.php
        ├─ inc/common_functions.inc.php
        │     ├─ class.quantivia_so.inc.php   PDO
        │     └─ class.quantivia_bo.inc.php   domain logic
        ├─ forms/*.php
        ├─ services/*.php
        ├─ dashboard/*.php
        └─ api/qvaapi.php

Workers
  quantivia/inc/worker.php  ← QFD/worker.vbs (quantivia.local.com)
  quantivia/inc/ofload.php  ← settings URL on online.quantivia.com

Data
  RDS MySQL (eu-west-1)
    ├─ quantiviagroupware   eGroupware
    └─ quantivia            Quantivia projects
  Files: /var/www/html/online.quantivia.com/files
```

Quantivia is not registered with an eGroupware `setup/setup.inc.php` in this tree. It is a directory of PHP endpoints that reuse the eGroupware session.

## Repository layout

| Path | Role |
|---|---|
| `phpgwapi/` | eGroupware 1.8.004 API |
| `header.inc.php` | Install root, domain database, session handler |
| `login.php`, `loginextra.php`, `logout.php`, `index.php` | eGroupware entry |
| `quantivia/` | Quantivia application |
| `actions/`, `ncr/`, `permit/`, `risk/`, `smt/`, `womt/` | Custom trackers |
| `organogram/` | Flash organogram |
| `QFD/` | Windows worker launcher |
| `setup/` | eGroupware setup |
| Other app directories | Stock eGroupware apps listed in `features.md` |
| `bitbucket-pipelines.yml` | FTP init pipeline (Indawo host on the QA branch step) |
| `README.md` | Indawo CodeDeploy / FTP notes |
| `web.config` | IIS default document `index.php` |
| `doc/` | eGroupware documentation shipped with the platform |

About 12,872 files are in the revision. Large vendor trees include `quantivia/smartadmin/`, `quantivia/jpgraph/`, `quantivia/lib/`, `quantivia/quantiviasqladmin/`, and `projectmanager/` chart-cache images.

## Languages and frameworks

| Layer | Technology | Evidence |
|---|---|---|
| Server | PHP | Application and eGroupware sources |
| UI | SmartAdmin (Bootstrap / jQuery assets) | `quantivia/smartadmin/` |
| Charts | JPGraph and JSON chart endpoints | `quantivia/jpgraph/`, `services/*.json.php` |
| Spreadsheets | PHPExcel | `quantivia/lib/PHPExcel/` |
| Mail library | PHPMailer | `quantivia/lib/PHPMailer/` |
| SQL admin UIs | phpMyAdmin fork and phpLiteAdmin | `quantiviasqladmin/`, `quantiviasqliteadmin/` |
| Data access | PDO, default driver mysql | `class.quantivia_so.inc.php` |
| Platform | eGroupware 1.8 (`phpgwapi` 1.8.004) | `phpgwapi/setup/setup.inc.php` |
| Organogram | Adobe Flash (`origramy.swf`) | `organogram/index.php` |
| Workers on Windows | VBScript and batch | `QFD/`, `TaskMasterLoop.bat` |

PHP language version is not declared in a `composer.json`. The pipeline image is `python:3.5.7` and is used to install `git-ftp`; it does not run the PHP app. The commented changelog key `1.2.093` says "Upgraded : PHP 7 Compatibility". That key is inside a comment. **Unknown / Requires Confirmation** which PHP version production used in 2019.

No `composer.json` and no `package.json` at the repository root were found in the file listing used for this document.

## Version identifiers in this revision

| Identifier | Value | Where |
|---|---|---|
| Git | `0af11d2` | `master` |
| Changelog tip (active) | `2.0.013` | `common_functions.inc.php` |
| Settings `version` before overwrite | `1.2.000` | `quantivia_setings.php` |
| SO | 216 | `class.quantivia_so.inc.php` |
| BO | 276 | `class.quantivia_bo.inc.php` |
| BO file `$Id` | `2.0.000` 2016-11-17 | class header |
| SO file `$Id` | `2.0.000` 2014-12-04 | class header |
| phpgwapi | 1.8.004 | setup |
| header versions | current header from phpgwapi setup; `'header' => '1.29'` | `header.inc.php` |
| Assembled runtime version | `{last changelog key} - (SO:{so} - BO:{bo})` | `common_functions.inc.php` |

`end()` plus `key()` on the changelog array selects the last inserted key. In this file that is `2.0.013`.

## Configuration

### `header.inc.php`

| Key | Value observed (non-secret) |
|---|---|
| `EGW_SERVER_ROOT` / `EGW_INCLUDE_ROOT` | `/var/www/html/online.quantivia.com` |
| Domain `db_type` | `mysql` |
| Domain `db_port` | `3306` |
| Domain `db_name` | `quantiviagroupware` |
| Domain `db_host` | RDS hostname in `eu-west-1` (see file) |
| `db_persistent` | true |
| `session_handler` | `egw_session_files` |
| `login_template_set` | `idots` |
| `mcrypt_enabled` | false |
| `show_domain_selectbox` | false |
| `setup_acl` | empty string |
| `header_admin_user` | `admin` |
| `DEBUG_API` / `DEBUG_APP` | false |

Also stored, and **not reproduced here**: database password, config password, header admin password, mcrypt IV. A commented block contains a localhost variant of the domain database with its own user and password.

### `quantivia/setup/quantivia_setings.php`

| Key | Value observed (non-secret) |
|---|---|
| Quantivia `db_name` | `quantivia` |
| Quantivia `db_port` | `3306` |
| Quantivia `db_host` | same RDS host as eGroupware |
| eGroupware db name in this file | `quantiviagroupware` |
| `version` (then overwritten) | `1.2.000` |
| `csv_symb` | comma |
| `report_period` / `time_report_period` | `4` |
| `cpu_cores` / `cpu_speed` | `30` / `30` |
| `ofload_location` | `https://online.quantivia.com/quantivia/inc/ofload.php` |
| `file_retention` | true |
| `file_storage` | `/var/www/html/online.quantivia.com/files` |
| `use_wincache` | false |
| `broker_cache` | `/var/www/html/online.quantivia.com/temp/QuantiviaCache` |
| `worker_url` / `worker_port` | `online.quantivia.com` / `80` |
| `EGW_SERVER_ROOT` redefined | `/var/www/html/online.quantivia.com` |
| `DPPR_INCLUDE_ROOT` | `/var/www/html/online.quantivia.com/quantivia` |
| Category id keys | `egw_bug_cat` 36, `egw_fea_cat` 35, `egw_gen_cat` 94, `egw_pmt_cat` 95 |

`PDO_type` is not set in this file. The data class then sets it to `mysql`.

Passwords and `excel_password` are omitted. A `debug_ip` value is set; the comment labels it "Jean DSL". The address is omitted.

## Data

**Implemented.**

- eGroupware data lives in the domain database (accounts, ACL table used as `EGW_GROUPS`, categories, app tables).
- Quantivia data lives in the Quantivia database. Project rows are read from `PROJECTS_TABLE` (class constant; physical name not expanded in the excerpts used here).
- Per-project tables are created through `quantivia/setup/sql_construct.php` when `PDO_type` is mysql. The sqlite branch includes `sqlite_construct.php`, which is **not in the tree**.
- Reporting method on a project may be stored serialized (`read_project_reporting_methods` calls `unserialize` on the `reporting` column).
- Schema migration history inside Git is a single import. There is no migration framework in the Quantivia directory beyond the SQL construct scripts.

**Unknown / Requires Confirmation:** the live table list, indexes, and whether `p_{id}_*` (or another prefix) is still the physical pattern. `sql_construct.php` was not line-reviewed for every `CREATE TABLE`.

## Authentication and sessions

- eGroupware login via `login.php`. Missing config redirects to `setup/index.php`.
- `loginextra.php` is a modified login dated 2016-11-22 in its `$Id` tag and calls `login_screen_extra`. No TOTP symbol was found in the repository.
- Session handler: files (`egw_session_files`).
- Quantivia shell requires cookies `sessionid` and `last_loginid`.
- `common_functions.inc.php` sets HTTP 403 if `sessionid` is missing, without an exit on that line.
- CAS is a branch inside `login.php` when `auth_type` is `cas`. This snapshot's `header.inc.php` does not set `auth_type` in the portion read (lines 1–141 cover the whole file). So the CAS branch is present in code and not selected by the committed header. **Implemented** code path, **not configured** in this header.
- `version.php` does not check a session cookie before including common functions. The common include then applies the 403-without-exit behaviour and continues into license logging.

## API surface (Quantivia)

| Endpoint | Role |
|---|---|
| `quantivia/main.php` | HTML shell |
| `quantivia/forms/*.php` | UI actions (see `features.md`) |
| `quantivia/services/*.php` | JSON and HTML fragments, filters, menu |
| `quantivia/dashboard/*.php` | Widgets |
| `quantivia/api/qvaapi.php` | Table export after token and session project check |
| `quantivia/api/status.php` | Present; body not summarised |
| `quantivia/version.php` | Version or `AD` |
| `quantivia/inc/worker.php` | Job runner (`job` or `task` query, or a poll loop) |
| `quantivia/inc/ofload.php` | Offload include targeted by settings URL |
| Root `json.php`, `soap.php`, `xmlrpc.php`, `webdav.php`, `groupdav.php`, `rpc.php`, `xajax.php` | eGroupware protocol endpoints |

`qvaapi.php` uses `HTTP_REFERER` as the token. That is **Implemented**. It is a weak credential channel. Documented here as behaviour, not as a recommendation.

## Background work

`worker.php` task types 0 through 15 are listed in `business-rules.md`. Type 11 has no body.

Invocation:

- `GET job` syncs subtasks for that job id.
- `GET task` greater than 0 nominates, checks out, and runs that task.
- Otherwise the script nominates a task and runs it.
- It sets `$_SESSION['worker']`, user `worker`, template `templates_procon8_01`.

`QFD/union.bat` launches ten `cscript worker.vbs` processes. `worker.vbs` GETs `http://quantivia.local.com/quantivia/inc/worker.php` and loops without incrementing its counter (the `Do Until i>10` condition does not change `i`).

`create_ofload_token` stores a 24-character key for 12 hours.

## Deployment and environments

| Signal | Target | Provenance |
|---|---|---|
| PHP constants | `/var/www/html/online.quantivia.com` | **Implemented** config |
| Worker URL in settings | `online.quantivia.com:80` | **Implemented** config |
| QFD script | `quantivia.local.com` | **Implemented** script |
| License hostname list | demo, QA, sdev, local, and `online.quantivia.com` | **Implemented** |
| `web.config` | IIS default document | **Implemented** file. The PHP paths are Linux paths |
| `README.md` | Indawo local vhost, AWS CodeDeploy app `CodedeployDev`, region `eu-west-1`, S3 bucket name `codedeploy` | **Documented**, product name does not match Quantivia |
| `bitbucket-pipelines.yml` | `master`: `git ftp init` with `FTP_*_LIVE`. `development`: `git ftp init` to `public_html/indawo.overdriveqa.co.za`. Push lines commented | **Implemented** YAML |
| Docker / appspec / Sonar properties | Not in the tree | **Implemented** absence |

No CI test step exists in the pipeline. The pipeline does not install PHP.

## Security notes (evidence, not a pentest)

- Production database passwords, an Excel password, a header-admin password, a config password, and an mcrypt IV are committed. They are omitted from this document. Rotation is a human action. **Requires confirmation** that the values are retired.
- `phpinfo.php` and `phpstats.php` are in the web root.
- `setup_acl` is empty.
- `qvaapi` trusts `HTTP_REFERER` as a token.
- `version.php` records posted license fields (`lic`, `mac`, `dom`, `ser`).
- Bundled `quantiviasqladmin` is a database administration UI inside the application tree.
- The license exception list includes the production hostname and `127.0.0.1`.

## Development and testing

- No Quantivia PHPUnit (or similar) suite was found. `phpgwapi/tests` and `phpfreechat/phpfreechat/testcase` are the test directories at depth 2.
- `forms/treeviewtest.php` and `services/JsonExample.php` are named like fixtures. They were not executed.
- There is no documented local setup for Quantivia. The README's local setup is for an Indawo database dump and `application/config/database.php`, which is not the Quantivia layout.
- `developer_tools` is the eGroupware translation-tools app.

## Monitoring

No application monitoring agent, health dashboard, or log shipper was identified. `phpsysinfo` is the eGroupware system-info app. `phpstats.php` is an unreviewed root script.

`cpu_cores` and `cpu_speed` in settings are static integers, not a live probe.

## Related Silicon Ark set

`silicon_ark/quantivia-svn/` documents a different Git repository (`quantivia-svn` at `ca64fae`, 2019-06-12). Do not treat that PRD as the specification of this tree. Overlap in product name and eGroupware layout is **Inferred** from the two trees both containing Quantivia. A file-by-file diff was not the basis of this document.

## Human confirmation

1. Confirm the production hostname, and whether the RDS instance named in config is still in use.
2. Confirm which worker host is real: `online.quantivia.com` or `quantivia.local.com`.
3. Confirm whether the Indawo pipeline belongs in this repository.
4. Confirm PHP version and web server (the tree contains both a Linux document root and an IIS `web.config`).
5. Rotate committed secrets if they were ever live.
6. Confirm whether the missing `sqlite_construct.php` and missing Quantivia `setup.inc.php` are accidental omissions from the import.
