# Business rules — indawo_docker

Evidence date: 2026-10-12. Revision: `main` `76c21e3`.

This repository is a local container stack. It does not implement Indawo domain rules (bookings, users, payments, or similar). No such rule was found in the tree. Rules below are the ones the compose file, Dockerfiles, sample env, script, and README actually state.

Labels:

- **Documented** — written in the README, `sample.env` comments, `todo.md`, or the script's usage text.
- **Implemented** — what the current files do.
- **Inferred** — a reading of those files, not a separate specification.
- **Removed** — true in `cc17467` or `2567dfc`, and not true on `main`.

## BR-PURPOSE — Local development only

The README says the stack is built for local development and is not for production use. It says a production deployment should at least change the PHP handler from `mod_php` to php-fpm and restrict MySQL users by source IP.

Provenance: **Documented**. The images still start Apache via `apache2ctl -D FOREGROUND` and do not add MySQL host grants. Provenance: **Implemented**.

## BR-STACK — What starts together

On `main`, one compose file starts a web server, a database, phpMyAdmin, and Redis. Web and database restart always. phpMyAdmin and Redis do not set a restart policy.

Provenance: **Implemented**.

The February rule was a PHP service plus a MySQL service, with MySQL 5.7 chosen "for better compatibility with PHP 5.6". Provenance: **Documented** and **Implemented** in that compose file. **Removed** as a comment. The current MySQL Dockerfile is still `mysql:5.7`, so the version choice remains. Provenance: **Implemented**.

## BR-PHP — Which PHP image is built

`PHPVERSION` selects the build context `./bin/${PHPVERSION}`. The sample file sets `php56`. Compose then builds the `Dockerfile` in that directory.

`Dockerfile2` in the same directory is not selected. Provenance: **Implemented**. A rule that says when to use `Dockerfile2` was **not found**.

`sample.env` and the README list other PHP versions. Image directories for those versions were **not found** on `main`. Selecting one would point Compose at a missing context. Provenance: **Inferred** from the path pattern.

`sample.env` says MySQL 8 is not supported for PHP `<= 7.4` because PDO support is lacking. Provenance: **Documented**. The build script skips `mysql8` for `php54`, `php56`, `php71`, `php72`, and `php73`, and includes `mysql8` from `php74` upward. Provenance: **Implemented** in `dev_build_container.sh`. Those other image directories are still absent.

## BR-DB — Database account and name

Uncommented sample values:

| Setting | Value in `sample.env` |
|---|---|
| `MYSQL_ROOT_PASSWORD` | `tiger` |
| `MYSQL_USER` | `docker` |
| `MYSQL_PASSWORD` | `docker` |
| `MYSQL_DATABASE` | `docker` |

Provenance: **Implemented** in the sample file. Compose passes them into the database container and into the web container environment. phpMyAdmin uses user `root` and `MYSQL_ROOT_PASSWORD`.

The README tells the reader to sign in to phpMyAdmin as `root` / `tiger`. Provenance: **Documented**.

A comment in `sample.env` says that if the docker user needs more databases than the `docker` database, privileges can be granted in phpMyAdmin. Provenance: **Documented**. No SQL grant script is committed.

A second commented block names user `silicon` and database `indawo_online`, with a password. That password is not recorded in this document. Commented lines are not applied by Compose. Provenance: **Documented**. Using that account is **not** an active rule.

Historical rule, **Removed** on `main`: `MYSQL_DATABASE` was `indawo`, user `user`, with development passwords committed in `docker-compose.yml`. The README of that revision said those credentials were for development only and must be changed before production. Provenance: **Documented** and **Implemented** at `2567dfc`.

`sample.env` says Apple Silicon users should select MariaDB. Provenance: **Documented**. No MariaDB Dockerfile is on `main`, and the sample file itself sets `DATABASE=mysql57`.

## BR-NET — Where ports are reachable

| Service | Publish | Sample host port |
|---|---|---|
| Web HTTP | `${HOST_MACHINE_UNSECURE_HOST_PORT}:80` | 80 |
| Web HTTPS | `${HOST_MACHINE_SECURE_HOST_PORT}:443` | 443 |
| MySQL | `127.0.0.1:${HOST_MACHINE_MYSQL_PORT}:3306` | 3306 |
| phpMyAdmin HTTP | `${HOST_MACHINE_PMA_PORT}:80` | 8080 |
| phpMyAdmin HTTPS | `${HOST_MACHINE_PMA_SECURE_PORT}:443` | 8443 |
| Redis | `127.0.0.1:${HOST_MACHINE_REDIS_PORT}:6379` | 6379 |

MySQL and Redis are bound to loopback. Web and phpMyAdmin publishes have no host IP, so Docker publishes them on all host interfaces. Provenance: **Implemented**. A written rule that this split is intentional was **not found**. The README says Apache is on port 80 at `http://localhost` and phpMyAdmin is on port 8080. Provenance: **Documented**.

The web service is linked to `database`. Provenance: **Implemented**. Application code that used the old hostname `mysql` would not match the current service name `database`. That consequence is **Inferred**. The old name is **Removed**.

## BR-FILES — What is mounted

| Host path (default) | Container path | Notes |
|---|---|---|
| `./www` | `/var/www/html` | Read-write. Gitignored |
| `-./filesystem` | `/var/www/filesystem` | Written as a volume string that begins with `-./`. **Inferred** typo. Not executed |
| `./config/php/php.ini` | `/usr/local/etc/php/php.ini` | Mounted twice, the second time via variable `FileSyem` |
| `./config/ssl` | `/etc/apache2/ssl/` | |
| `./config/vhosts` | `/etc/apache2/sites-enabled` | README says each vhost needs a host `hosts` file entry |
| `./logs/apache2` | `/var/log/apache2` | Compose variable is `LOG_DIR`. Sample file sets `APACHE_LOG_DIR` to the same path and does not set `LOG_DIR` |
| `./logs/xdebug` | `/var/log/xdebug` | |
| `./config/initdb` | `/docker-entrypoint-initdb.d` | README: first start runs `.sh`, `.sql`, `.sql.gz`, and `.sql.xz` in alphabetical order. `.sh` without execute permission is sourced |
| `./data/mysql` | `/var/lib/mysql` | |
| `./logs/mysql` | `/var/log/mysql` | README text for this variable says "Apache logs". The directory name is `mysql`. Provenance: **Documented** wording |

Provenance of the mounts: **Implemented**, except the README sentences, which are **Documented**.

`/config/*`, `/data/*`, `/logs/*`, and `/www/**` are gitignored, so the running site and the database files are local. Provenance: **Implemented**.

The February mount of `/external/drive` onto `/external` is **Removed**. The README of that revision required the path to exist and to be writable by the container user. That rule is no longer in the current README.

## BR-ODBC — SQL Server client

The default PHP Dockerfile writes FreeTDS host `your_sql_server_host`, port `1433`, TDS version `7.4`, and an ODBC driver named `FreeTDS`. Provenance: **Implemented**.

No compose environment variable supplies a real host, database, user, or password for that DSN. Provenance: **Implemented** absence.

The February image's rule was different: a DSN named `MSSQL` used `ODBC Driver 13 for SQL Server` and `${MSSQL_HOST}` / `${MSSQL_DATABASE}`, with credentials only in the process environment. Provenance: **Removed**.

No rule was found that says which SQL Server this stack must reach.

## BR-XDEBUG — Debugger port

The image enables Xdebug 2 with `xdebug.remote_enable=1`. The sample environment sets `XDEBUG_PORT=9003`. The README's Xdebug 2 example uses port 9000, and its Xdebug 3 example uses port 9003.

Provenance: **Implemented** image and sample port. **Documented** README split. The combination on `main` points an Xdebug 2 install at port 9003. **Inferred** from those files. Not executed.

## BR-PHPINFO — Default document in the image

`bin/php56/Dockerfile` installs a phpinfo script as `/var/www/html/index.php`. Provenance: **Implemented**.

`Dockerfile2` does not. Provenance: **Implemented**.

No rule was found that requires phpinfo to remain in the image. The README does not mention it.

## BR-SCRIPT — Matrix builds delete MySQL files

`dev_build_container.sh` is for Linux. On any other `uname` it prints that only Linux is supported and exits. Provenance: **Implemented**.

Before each build it runs `rm -rf ./data/mysql/*`. The usage text says the script removes all data in `data/mysql/*`. Provenance: **Implemented** and **Documented**.

It expects curl of `http://localhost/test_db.php` and `http://localhost/test_db_pdo.php` to contain `proper` exactly once. Anything else stops the containers and exits. Provenance: **Implemented**. Those PHP files are not in the repository, so the success rule cannot be satisfied from git alone. Provenance: **Inferred**.

The script's env rewrite looks for `PHPVERSION=php8` and `DATABASE=mysql8`. `sample.env` does not contain those strings. Provenance: **Implemented**.

## BR-SECRETS — What git is allowed to hold

`.env` is gitignored. `sample.env` is committed and contains the active development passwords above plus one commented password that is not copied here. Provenance: **Implemented**.

A rule that forbids committing that commented password was **not found**. Whether it is still valid is **Unknown / Requires Confirmation**.

## BR-NAME — Indawo

The git remote and the February database name `indawo` are the evidence that this stack was aimed at something called Indawo. Provenance: **Implemented** (remote; historical compose).

The current README never uses the word Indawo. The current applied database name is `docker`. The commented database name is `indawo_online`.

No business rule in this repository defines who may use an Indawo product, what data it stores, or how it behaves. Those rules would live in the application mounted from `./www`, which is not part of this commit.
