# Project plan — indawo_65

Evidence date: 2026-10-12.

Source repository: `git@bitbucket.org:overdrive/indawo_65.git`.

This plan describes what that repository contains. It does not decide what the product should become.

The scan-host path named on the onboarding issue (`~/projects/sonar_scan/repos/indawo_65`) was not on this machine. The tree below was read from a clone of branch `INDAWO_84_2026`. The issue recorded commit `3699fee` (2026-02-17 13:46 +0200, "order 8.4 upgrades"). That commit is an ancestor of the branch tip. The tip read here is `08157c5` (2026-03-24 12:30:28 +0200, Ettiene, "f ixed cronjob syncs"). `git ls-remote --heads` on 2026-10-12 returned the same tip, so this branch had not moved between 24 March 2026 and the evidence date.

There is no prior Silicon Ark set for `indawo_65`. Silicon Ark already has sets for `indawo_84`, `indawo_docker`, and `indawo_online_docker`. Those are other repositories. They are not a description of this tree.

## Product

The Git remote and the onboarding issue name the repository `indawo_65`. The application calls itself **Indawo Online**.

| Identity | Where | Provenance |
|---|---|---|
| Repository `indawo_65` | Git remote | **Implemented** |
| Composer package `russel-sauer/indawo`, description "PHP Indawo Project" | `composer.json` | **Implemented** |
| Product name "Indawo Online" | `login.php` (TOTP issuer and login log label), `README.md` title `indawo_online` | **Implemented** and **Documented** |
| MySQL database `indawo_online` on most hosts; `sil27_indawo_online` on `silicon-overdrive.co.za` | `system.php` | **Implemented** |
| Public host `online.indawo.biz` | `system.php` case, comment "LIVE LIVE" | **Implemented** |
| Production install path `/var/www/indawo` | `setup_composer.md` | **Documented**. Session paths in `system.php` use `indawo_online` or `SESSION` under the document root. The two paths are not the same string |

Indawo Online is a PHP web application for construction-company operations: clients and contacts, jobs and enquiries (Foreman), purchase orders and authorisation, invoices, pre-start agreements, budget adjustments, job suggestions, assets, cash-flow and management dashboards, and users. MySQL holds the online copy. Microsoft SQL Server (`CPTSQL02` on the live-named hosts, other server names on older host cases) is the Foreman / back-office system reached over ODBC. Provenance: **Implemented** in `system.php`, the page scripts, and the cron file headers. A written architecture document is not in this repository.

`indawo_84` (Silicon Ark, evidence date 2026-10-12) is a later repository with the same composer package name, the same product name, and the same Sonar project key `overdrive_indawo_65_fbe8b635-8a1f-460d-ad73-ab11cacca02f`. Its `main` includes a realtime sync queue, money-impact views, and an ODBC dashboard that are not in this `indawo_65` tree. Whether `indawo_65` is still a deployed line, or has been superseded by `indawo_84`, is **Unknown / Requires Confirmation**.

## Branch reality

`git ls-remote --heads` on 2026-10-12. No tags were returned.

| Ref | Tip | Date and subject where the object was local | Relation to `INDAWO_84_2026` |
|---|---|---|---|
| `INDAWO_84_2026` | `08157c5` | 2026-03-24, "f ixed cronjob syncs" | Branch that was read |
| `master` | `80c67f5` | 2026-01-29, "bitbucket-pipelines.yml created online with Bitbucket" | Ancestor of `INDAWO_84_2026` |
| `feature/development/20260203-RS-PHP-8.4-Upgrade` | `f29b04e` | Object is in this branch's history | Ancestor |
| `feature/development/20260213-RS-security-update-switch-to-env` | `937a05b` | Object is in this branch's history | Ancestor |
| `feature/development/20260213-RS-security-update-mfa` | `f378137` | Object is in this branch's history | Ancestor |
| `feature/development/20260219-RS-security-update-deactivate-users` | `792e613` | Object is in this branch's history | Ancestor |
| `feature/development/20260220-RS-security-update-password-policy` | `fa114e3` | 2026-02 password-policy commit message on this branch | Ancestor |
| `dev` | `3194af1` | 2022-11-30, "no message" | Not an ancestor. How `dev` differs was not read |
| `dev-30-06-2022` | `03e8482` | 2022-05-20, "Removed spaces from case statement" | Not compared |
| `hotfix/DuplicationOfOrdersOnRefresh` | `dcd39bf` | 2022-12-07, "init" | Not compared |
| `new_pdfs` | `6194b20` | 2022-07-26, "remove pdf from git" | Not compared |

There is no `main` branch. `origin/HEAD` was not re-checked beyond the heads above. This onboarding read `INDAWO_84_2026` only.

Work after the issue's recorded commit `3699fee` (34 commits, `3699fee..08157c5`):

- MFA setup and verify, remember-device for 30 days, recovery codes, admin enablement, deletion of expired remember-device tokens.
- Inactive-user deactivation (bulk, six months, and selected users) and notification email templates.
- Password expiry on login.
- PHP 8.4 fixes on orders, search, contact log, KPI, toolbars, Nemo warnings, and dashboard PDFs.
- Pre-start, job, and contact changes (`de4291a`, `2bc9634`, `1bb8ae0`).
- Cron sync fix at the tip (`08157c5`).

`CHANGELOG.md` and `README.md` stop at 2026-02-11 (PHP 8.4 null and quoting fixes). They do not record the MFA, deactivation, password-expiry, or March 2026 commits. Provenance: **Documented** lag.

## Scope on `INDAWO_84_2026`

In the committed application (libraries under `mpdf/`, `PHPExcel/`, `html2pdf/`, and `plugins/` excluded from this list):

- Page scripts for login, home, clients, contacts, contact log, jobs, enquiries, orders, order authorisation, invoices, pre-start agreements, budget adjustments, job suggestions, job types, assets, companies, sales people, users, security groups, settings, email, messages, my tasks, KPI, dashboards, search, archived, and reports.
- A Nemo page framework (`_nemo*.cls.php`) for lists, details, menus, email, reports, passwords, and MySQL.
- ODBC access to SQL Server (`_nemo.database.SQL_SERVER.cls.php`, `_sync.cls.php`).
- Nightly batch sync crons (lookups, clients, Foreman, data dumps), cash-flow PDF generation, order-authorisation email, and monthly order cancellation for company ids 1, 4, 6, and 9.
- Per-record SQL Server update when a job suggestion is accepted (`SyncRecord` in `includes/job.suggestion.cls.php`). There is no `sysSyncQueue` file or symbol in this tree.
- Composer dependencies for PHP 8.4, dotenv, TOTP, QR codes, and PDF (`composer.json`).
- Two-factor authentication pages and `MFATables.sql`.
- User deactivation SQL seed for two email templates (`includes/UserAccountDeactivation.sql`).
- A Bitbucket Pipelines file that runs SonarQube on the branch pattern `{master}`.

Out of the committed tree, though named by code or docs:

- `.env` (gitignored). The tracked template is the file named `env`. Dotenv is loaded for every host. Only the `localhost`, `127.0.0.1`, and default cases read `DB_*` from the environment.
- `vendor/` (`composer.json` says not to commit it).
- `SESSION/`, `orders/`, `RequestInvoice/`, `ProfitOverviewPDF/`, `JobReport/`, and logs (`.gitignore`).
- A live MySQL schema dump. `MFATables.sql` and `includes/UserAccountDeactivation.sql` are the only schema scripts found. They alter or insert; they are not a full schema.
- Crontab on the live host. Cron behaviour is in the PHP files. The schedule that invokes them is **Unknown / Requires Confirmation**.
- The `dev` tree and the 2022 hotfix / PDF branches.

`Cash Flow Report/` is listed in `.gitignore`. Whether tracked PDFs remain in history was not enumerated. The directory name is in the ignore file.

Not in this tree, though present in the later `indawo_84` repository: `docs/`, `http_cron_gate.php`, `.htaccess`, `ODBC_connections.php`, `includes/syssyncqueue_schema.inc.php`, `includes/job.money.impact.inc.php`, and the morning/evening realtime crons. Provenance: file search on this checkout returned no matches.

## Architecture (summary)

```text
Browser
  -> PHP 8.4 page (Nemo) + session ONLINE
  -> MySQL (indawo_online, or sil27_indawo_online on silicon-overdrive.co.za)
  -> ODBC -> SQL Server (CPTSQL02 / SQL-SERVERR2 / FreeTDS, database CLIENTS or ind_INDAWO depending on host)

Crons (PHP scripts; no HTTP gate file in this tree)
  -> Sync class, staging then live tables
  -> PDFs / Excel
  -> email via NemoEmail
```

Host selection is a `switch` on `$_SERVER["SERVER_NAME"]` in `system.php`. Named cases include `debian`, `lamp`, `silicon-overdrive.co.za`, `192.168.100.31`, `online.indawo.local`, `online.indawo.biz`, `192.168.0.28`, `localhost`, and `127.0.0.1`, plus a default that rewrites the host to `localhost`. Credentials for the non-local cases are literals in `system.php`. They are not copied into Silicon Ark.

Detail is in `technical-documentation.md`.

## Milestones visible in the repository

| When | What the repository shows | Status |
|---|---|---|
| 2014–2017 comments | Login lock, password framework, order-cancel moved to the 15th, order-auth email | **Implemented** comments in `login.php` and the cron files. Not a project plan |
| 2026-01-29 | `master` tip adds `bitbucket-pipelines.yml` | **Implemented** on `master`, which is behind `INDAWO_84_2026` |
| 2026-02-03 to 2026-02-11 | PHP 8.4 quoting and null guards | **Documented** in `CHANGELOG.md` and **Implemented** |
| 2026-02-13 to 2026-02-20 | MFA, env switch for local hosts, user deactivation, password expiry | **Implemented** on `INDAWO_84_2026`. The feature-branch tips are ancestors |
| 2026-02-17 | Issue snapshot `3699fee`, "order 8.4 upgrades" | Ancestor of the tip |
| 2026-02-17 to 2026-03-24 | Further PHP 8.4 fixes, pre-start, job, contact, dashboard PDFs, cron sync | **Implemented** at `08157c5` |
| After 2026-03-24 | No newer commit on `INDAWO_84_2026` as of 2026-10-12 | **Implemented** pause on this branch |

No milestone document or roadmap file was found.

## Current status

- The branch the issue named is `INDAWO_84_2026`, tip `08157c5`, 34 commits after the issue snapshot.
- `master` is an older ancestor (2026-01-29). Pipelines are configured for `{master}` only, so the branch that contains the 2026 security work is not the branch the pipeline pattern names. Whether pipelines also run on other branches in the Bitbucket UI is **Unknown / Requires Confirmation**.
- `README.md`, `CHANGELOG.md`, and `NewKnowledgeBase.md` describe PHP 8.4 fixes through 2026-02-11 and do not describe MFA, deactivation, or password expiry.
- Login, MFA, company scoping, nightly SQL-to-MySQL sync, cash-flow PDFs, and order cancel are implemented in code.
- Realtime queue, HTTP cron gate, and the ODBC dashboard from `indawo_84` are absent here.
- `cron.daily.repeater.update.php` only prints that it is a temporary file.
- User-deactivation mail is overridden in code to test recipients. A comment says the administrator address is still up for discussion.
- Plaintext database passwords are in `system.php` for named hosts. They are omitted from these documents.

## Known dependencies

- PHP `>=8.4`, `ext-gd`, and the extensions named in `setup_composer.md` (`mysqli`, and recommended `mbstring`, `openssl`, `curl`, `odbc`).
- Composer packages: `vlucas/phpdotenv` `^5.6`, `robthree/twofactorauth` `^3.0`, `endroid/qr-code` `^6.1`, `mpdf/mpdf` `^8.2`, `spipu/html2pdf` `^5.3`.
- Vendored `mpdf/`, `PHPExcel/`, `html2pdf/`, Highcharts, and canvg under `plugins/`.
- MySQL database named above.
- Microsoft SQL Server via ODBC. `setup_composer.md` tells the operator to create a system DSN named `CPTSQL02` at `192.168.0.9,53950`.
- SMTP settings loaded as `SystemSettings["SMTP Send As"]` and `SMTP BCC`. The server host is **Unknown** from this pass; it is not a constant in the files that were read.
- Bitbucket Pipelines and a SonarQube server (`SONAR_HOST_URL`, `SONAR_TOKEN`). The project key is in `sonar-project.properties`.

## Implementation plan (as evidenced, not proposed)

There is no forward plan file in the repository. The implemented sequence visible from history is: keep the Nemo page application, harden it for PHP 8.4, add MFA and password expiry, add inactive-user deactivation, and keep the nightly SQL Server pull. Anything beyond the March 2026 tip is not specified here.
