# PRD — quantiviaLive (Quantivia on eGroupware)

Evidence date: 2026-10-05.

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

There is no prior PRD in this directory of Silicon Ark and no product requirements document in the source repository. Requirements below are recovered from the implementation (primarily `quantivia/`), eGroupware app metadata, and the in-code changelog. Provenance is labelled. Credential values are not reproduced.

## Product purpose

**Documented.** `quantivia/inc/class.quantivia_bo.inc.php` describes Quantivia as a **Deliverable Progress and Performance Reporting tool** (eGroupware Friendly), commercial license, author Jean Thirion / PROCON8, copyright 2017.

**Implemented.** An authenticated eGroupware user opens `quantivia/main.php`, selects a project, maintains deliverables, control-point chains, resources, and budgets, and views or publishes RAMP/STEP progress reports through a SmartAdmin shell.

**Also implemented (platform).** The same tree is an eGroupware 1.8 groupware install (`phpgwapi` 1.8.004) with mail, calendar, address book, file manager, and custom trackers (actions, NCR, permit, risk, SMT, WOMT).

**Unknown / Requires Confirmation:** whether Overdrive or Procon8 still operates this snapshot as a live product, and which client programmes remain in scope.

## Users and roles

Roles are **Implemented** in `quantivia/inc/class.quantivia_so.inc.php` and enforced on pages that include `quantivia/inc/common_pageSetup.php`.

| Actor | How the code decides | Status |
|---|---|---|
| eGroupware account holder | `login.php` creates a session. Quantivia reads cookies `sessionid` and `last_loginid` | **Implemented** |
| Site administrator | Member of eGroupware group `Admins` (`is_user_admin`). Account id `-1` is also treated as site admin so workers can run | **Implemented** |
| Project administrator | Member of eGroupware group `P_{id}_admin`, or the project's `administrator` column equals the user id | **Implemented** |
| Progress administrator | Member of `P_{id}_p_admin`. Members of `P_{id}_admin` are also treated as progress administrators | **Implemented** |
| Project user | Member of `P_{id}`. Members of `P_{id}_admin` are also treated as project users | **Implemented** |
| Programme user | Member of an eGroupware group whose name is the programme name (`is_user_programme_user`) | **Implemented** |
| Worker process | `$_SESSION['worker']` is set; `get_uid` returns `-1`; `$GLOBALS['current_user']` is set to `worker` | **Implemented** |
| Header/setup admin | `header.inc.php` `header_admin_user` is `admin`. Password value omitted | **Implemented** |
| Licensed installation | MAC plus domain match against license constants, or the request hostname is on the exception list | **Implemented** |

`checkCurrentUserAutherization($allowSiteAdmin, $allowProjectAdmin, $allowProjectUser, $allowProjectProgressAdmin)` returns immediately when an allowed role matches. Otherwise it prints one of:

- `Access Denied: User does not have site administration rights` (HTTP 401)
- `Access Denied: User does not have project administration rights` (HTTP 401)
- `Access Denied: User is not a member of this project.` (HTTP 401)
- `Access Denied: This feature is locked for all user types.` (HTTP 401)

`requireFullLicence()` prints `This system is in Demo mode, and can not use this function` and returns HTTP 401 when `$_SESSION['licensed']` is false.

A per-form matrix of which flag combination each `forms/*.php` file passes is **Unknown / Requires Confirmation** (not enumerated in this pass).

`loginextra.php` is a 2016 Jean Thirion variant of the eGroupware login (`$Id` 2016-11-22) that redirects to itself and calls `login_screen_extra`. A search of this tree found no `TOTP` or `GoogleAuthenticator` symbol. Whether that extra screen adds a second factor is **Unknown / Requires Confirmation**. There is no `auto_login.php` in this tree.

## Systems the product talks to

1. The user's browser (SmartAdmin HTML and JavaScript).
2. eGroupware MySQL database. Configured name `quantiviagroupware`, type `mysql`, host an RDS endpoint in `eu-west-1`. Host name is in `header.inc.php`. Password omitted.
3. Quantivia database. Configured name `quantivia`, same RDS host, PDO. Default driver `mysql` when `PDO_type` is unset.
4. File storage path `/var/www/html/online.quantivia.com/files` and broker cache `/var/www/html/online.quantivia.com/temp/QuantiviaCache`.
5. Offload endpoint configured as `https://online.quantivia.com/quantivia/inc/ofload.php`.
6. License constants read via `sg_get_const` (`L_DOMAIN`, `L_MAC`, `L_COMPANY`, `N_PROJECTS`, `L_SERIAL`, `L_TYPE`). The license file format itself was not opened in this pass.
7. Primavera P6 files (XER, ZIP, XML) through `quantivia/forms/p6import.php`.
8. Optional eGroupware protocol endpoints present at the web root: `groupdav.php`, `webdav.php`, `soap.php`, `xmlrpc.php`, `json.php`, `rpc.php`, `xajax.php`. Their payloads are stock eGroupware behaviour (**Inferred** from file presence).
9. `quantivia/api/qvaapi.php` returns project tables (deliverables and others) after a token check.

SMTP via `class.quantivia_notifier.inc.php` is present. The mail host is **Unknown / Requires Confirmation** (not in the settings block that was read).

## Major workflows

### Sign in and open Quantivia

1. User opens `login.php` (or `loginextra.php`).
2. If `header.inc.php` is missing or `CreateObject` is unavailable, the script redirects to `setup/index.php`.
3. On success, eGroupware sets session cookies.
4. `quantivia/main.php` redirects to `../index.php` when `sessionid` or `last_loginid` is missing.
5. The SmartAdmin shell loads navigation, a dynamic dialog, and form endpoints.

Provenance: **Implemented**.

### Select and administer a project

1. `forms/SelectProject.php` and `services/ProjectSelection.php` list projects.
2. `display_all_projects()` in the business object reads all projects, drops id `-1`, and defaults missing tabular and graphical reporting methods to `RAMP`.
3. If the session is not licensed, the list stops after the first project (comment: demo).
4. If licensed, the list stops after `$_SESSION['N_PROJECTS']` rows.
5. Edit controls (`f` in the control style) are added only when the user is a project admin or site admin and the session is licensed.
6. Creating a project ensures eGroupware groups `P_{id}`, `P_{id}_admin`, and `P_{id}_p_admin` exist (`get_project_group_id` and the admin variants).

Provenance: **Implemented**.

### Maintain structure, progress, and resources

Forms under `quantivia/forms/` cover deliverables, control points, chains, budgets, resources, commitments, actual hours, calendars, and change instances. Heavy uploads are handed to `worker.php` by task type (see technical documentation). Online statusing and turnaround downloads are described in changelog keys `2.0.001`–`2.0.013`.

Provenance: **Implemented** (files and worker branches exist). The exact validation message for every upload is **not fully enumerated** here.

### Report and publish

Dashboard widgets under `quantivia/dashboard/` and JSON services under `quantivia/services/` feed progress, performance, S-curve, budget, resource, trend, and control-point charts. `forms/PublishReport.php` leads to worker task type 6 (`publish_report`). Reporting methods named in code are `RAMP` (Ramp Method) and `STEP` (Step Method).

Provenance: **Implemented**.

### Import a Primavera P6 schedule

`forms/p6import.php` titles the screen "Primavera P6 File Import" and states that the function supports P6 XER, ZIP, and XML files. XML is translated toward XER (`translate_P6_xml_to_xer`). Comments written on import include `Imported with P6 Import Wizard` and `Added by P6 Import Wizard`.

Provenance: **Implemented**.

## Functional requirements recovered from the implementation

### FR-001 — Session required for the Quantivia shell

**Requirement.** `quantivia/main.php` sends the browser to `../index.php` when the `sessionid` cookie is missing or when `last_loginid` is missing.

**Trigger.** Request to the Quantivia shell.

**Output.** Redirect, or the SmartAdmin page.

**Evidence.** `quantivia/main.php`.

**Implementation.** Implemented.

**Confidence.** High.

### FR-002 — Role gate on pages using common page setup

**Requirement.** A page that calls `checkCurrentUserAutherization` allows the request only for the roles it passes as true. Failure ends the request with HTTP 401 and one of the access-denied strings listed above.

**Evidence.** `quantivia/inc/common_pageSetup.php`.

**Implementation.** Implemented.

**Confidence.** High for the function. Medium for coverage, because not every form was checked for a call.

### FR-003 — License limits the project list

**Requirement.** An unlicensed session lists only the first project. A licensed session lists at most `N_PROJECTS` projects. On the hostname exception list, `N_PROJECTS` is set to 25 and `licensed`, `Elicensed`, and `Qlicensed` are set true.

**Evidence.** `common_functions.inc.php` license block; `quantivia_bo::display_all_projects()`.

**Implementation.** Implemented.

**Confidence.** High.

### FR-004 — Project groups in eGroupware

**Requirement.** Each project has member, admin, and progress-admin groups named `P_{id}`, `P_{id}_admin`, and `P_{id}_p_admin`. Missing groups are created.

**Evidence.** `class.quantivia_so.inc.php` `get_project_group_id`, `get_project_admingroup_id`, `get_project_progress_admingroup_id`.

**Implementation.** Implemented.

**Confidence.** High.

### FR-005 — Default reporting method

**Requirement.** When a project row has no tabular or graphical reporting method, the project list displays `RAMP`.

**Evidence.** `display_all_projects()`.

**Implementation.** Implemented.

**Confidence.** High.

### FR-006 — Dual database

**Requirement.** eGroupware accounts and ACL use the domain database (`quantiviagroupware` in this snapshot). Quantivia project data uses the Quantivia PDO database (`quantivia` in this snapshot).

**Evidence.** `header.inc.php`, `quantivia_setings.php`.

**Implementation.** Implemented as configuration. Whether those databases still exist is **Unknown / Requires Confirmation**.

**Confidence.** High for the configuration. Low for current operations.

### FR-007 — Offload long work

**Requirement.** Import, publish, and download jobs run through `quantivia/inc/worker.php`, which checks out an offloaded task and dispatches on `type_id` 0–15.

**Evidence.** `worker.php`.

**Implementation.** Implemented. Task type 11 (time download) has an empty branch.

**Confidence.** High.

### FR-008 — External table API

**Requirement.** `quantivia/api/qvaapi.php` rejects the request with HTTP 403 when the token does not validate, when the account cannot be read, or when the requested project id is not the project stored in the user's session. A missing `pid` is "Invalid Project". The default table is `all`. The `deliverables` table is one implemented branch.

**Evidence.** `quantivia/api/qvaapi.php`.

**Implementation.** Implemented.

**Confidence.** High for the gate. Medium for the full table catalogue (the file continues past the deliverables branch).

### FR-009 — P6 file types

**Requirement.** The P6 import screen tells the user it supports P6 XER, ZIP, and XML files.

**Evidence.** `quantivia/forms/p6import.php`.

**Implementation.** Implemented.

**Confidence.** High for the stated types. Parser edge cases were not executed.

### FR-010 — Demo lock

**Requirement.** `requireFullLicence()` blocks the current request when the session is not licensed, with the demo-mode message and HTTP 401.

**Evidence.** `common_pageSetup.php`.

**Implementation.** Implemented where called.

**Confidence.** High for the function.

## Integrations

| Integration | Direction | Trigger | Data | Auth | Failure |
|---|---|---|---|---|---|
| eGroupware session | Inbound from browser | Login | Session cookies | eGroupware account | Redirect to setup or index |
| eGroupware MySQL | Read/write | Account, ACL, groups, tracker categories | Accounts, groups, categories | DB credentials in `header.inc.php` | Not separately handled in the excerpts read |
| Quantivia MySQL | Read/write | Project operations | Projects and per-project tables | DB credentials in `quantivia_setings.php` | PDO errors were not catalogued |
| P6 files | Inbound upload | P6 import form | XER, ZIP, XML | Quantivia session (form is inside the app) | On-screen upload limit message |
| qvaapi | Inbound HTTP | `GET` table and `pid` | Deliverable and other tables | Token plus session project match | HTTP 403 and a short text reason |
| Offload URL | Outbound HTTP as configured | Workers | Task payload | Worker session flag | **Unknown / Requires Confirmation** |
| License constants | Local read | Every include of `common_functions.inc.php` | MAC, domain, project cap, type flags | License file via `sg_get_const` | Unlicensed session; demo project cap |

## Important constraints

- Timezone is forced to UTC in `common_functions.inc.php`.
- A 32-bit PHP timestamp ceiling is stored as `$_SESSION['maxtime'] = 2147472000` (comment: 19 Jan 2038 00:00:00 UTC, must be midnight).
- `report_period` and `time_report_period` are configured as `4` (comment: weeks).
- `file_retention` is true. `use_wincache` is false.
- `cpu_cores` and `cpu_speed` are both set to 30 in this snapshot.
- Offload tokens from `create_ofload_token` are 24-character alphanumeric strings with a 12-hour time to live (`43200` seconds).
- Version strings disagree. See project plan. The string assembled at runtime is the last changelog key plus SO and BO integers: `2.0.013 - (SO:216 - BO:276)` given the arrays in this revision.
- `quantivia/setup/sqlite_construct.php` is required by the SQLite schema branch and is absent.

## Error and edge conditions observed in code

| Condition | Behaviour | Provenance |
|---|---|---|
| No `header.inc.php` at login | Redirect to `setup/index.php` | **Implemented** |
| Missing `sessionid` inside `common_functions.inc.php` | HTTP 403 is set; the following line does not exit | **Implemented** |
| Missing session on `main.php` | Redirect to `../index.php` | **Implemented** |
| Role check fails | HTTP 401 and a translated denial string, then exit | **Implemented** |
| Unlicensed feature behind `requireFullLicence` | HTTP 401 and demo-mode message | **Implemented** |
| qvaapi token, user, or project mismatch | HTTP 403 and a text reason | **Implemented** |
| Unlicensed project list | First project only | **Implemented** |
| Worker task type 11 | Empty branch | **Implemented** |
| SQLite schema build | Include of a file that is not in the tree | **Implemented** reference, missing file |

## What this PRD does not claim

- That the RDS instance, the FTP pipeline, or `online.quantivia.com` is still in service.
- That the Indawo text in `README.md` is a Quantivia requirement.
- That every form's validation rules were read. Business rules below the role and license layer are in `business-rules.md` only where a specific code path was read.
